Вот ваша проблема "со строками кода!" :
//of course the problem has noting to do with the string being volatile...
private volatile string mainBuffer = string.Empty;
byte[] buffer = new byte[1024];
while (networkStream.Read(buffer, 0, buffer.Length) > 0)
{
string data = System.Text.Encoding.UTF8.GetString(buffer);
Console.WriteLine("Raw data: {0}", data));
mainBuffer += data;
Console.WriteLine(mainBuffer);
}
Естественно, вывод этого кода будет таким, как вы упоминали ранее.Вот что происходит:
Класс string
в C # - это массив char
, начинающийся с указателя на первый char
в массиве и заканчивающийся специальным "терминальным" char \0
,Когда вы создаете байтовый массив индекса n
, он заполнит все индексы массива значением по умолчанию byte
, равным 0
.но 0
просто равен символу терминала \0
byte b = (byte)`\0`;\\the value of b will be 0
Итак, когда вы вызываете Read(buffer)
, метод не будет обрезать буфер до соответствия прочитанные данные.поэтому, если размер буфера «здесь 1024» больше, чем считанные данные, все оставшиеся байты буфера будут равны терминалу char '\ 0', поэтому массив символов сгенерированной строки будет ABC\0\0\0\0... to the index 1024
.Когда вы добавляете строку DEF
к ней, она будет добавлена в последний индекс массива char
«после последнего \0
», тогда массив char
будет ABC\0\0\0\0...DEF
, но из-за DEF
добавляется после char (s) терминала, поэтому Console.Write
будет игнорировать все после первого \0
!.
Также обратите внимание, что во время отладки, если вы наведите указатель мыши на переменную mainBuffer
, вы увидите фактические данные, которые она содержит, может быть, что-то вроде ABC\0\0\0\0..DEF\0\0\0\0..GHI
Однако, чтобы решить проблему и создать только надежную строку, получите фактическое чтение байтов и сгенерируйте строку только из нее.Итак:
int dataRead = 0;
while ((dataRead = networkStream.Read(buffer, 0, buffer.Length)) > 0)
{
List<byte> actualBuffer = (new List<byte>(buffer)).GetRange(0, dataRead);
string data = System.Text.Encoding.UTF8.GetString(actualBuffer.ToArray());
Console.WriteLine("Raw data: {0}", data));
mainBuffer += data;
Console.WriteLine(mainBuffer);
}
Глупо упоминать здесь, что вы должны рассмотреть возможность использования StringBuilder вместо string
.