Байты используются StreamReader

Я прилагаю вам решение на основе data.table:

library(data.table)
my.df <- data.frame(a = rnorm(10,5), b= rnorm(10,5), c=rnorm(10,5), d=rnorm(10,5), e=rnorm(10,5))
my.df <- as.data.table(my.df)
my.df[my.df[,(sum(a<=.SD)<=2) | (sum(b<=.SD)<=2), by=seq_len(nrow(my.df))]$V1]
8
задан Jon Norton 10 April 2009 в 11:56
поделиться

5 ответов

Вы можете узнать, сколько байтов на самом деле вернуло StreamReader (в отличие от чтения из потока) несколькими способами, ни один из которых не слишком прост I ' я боюсь.

  1. Получите результат textReader.CurrentEncoding.GetByteCount (totalLengthOfAllTextRead) , а затем ищите эту позицию в потоке.
  2. Используйте некоторую хакерскую рефлексию, чтобы получить значение закрытой переменной объект StreamReader , который соответствует текущей позиции байта во внутреннем буфере (отличается от того, что с потоком - обычно позади, но, конечно, не более чем равен). Судя по .NET Reflector, эта переменная, кажется, называется bytePos .
  3. Don ' не стоит использовать StreamReader , но вместо этого реализуйте пользовательскую функцию ReadLine, построенную поверх потока Stream или BinaryReader даже ( BinaryReader гарантированно никогда не читать дальше, чем вы просите). Эта пользовательская функция должна считывать из потока char в char, так что вам действительно придется использовать низкоуровневый объект Decoder (если только кодировка не ASCII / ANSI, в этом случае все немного проще из-за к однобайтовому кодированию).

Вариант 1 будет наименее эффективным, как я себе представляю (так как вы эффективно перекодируете текст, который вы только что декодировали), а вариант 3 труднее всего реализовать, хотя, пожалуй, самый элегантный , Я бы, вероятно, рекомендовал не использовать некрасивый взлом отражения (вариант 2), хотя это выглядит заманчиво, будучи самым прямым решением и занимая всего пару строк. (Если честно, класс StreamReader действительно должен предоставлять эту переменную через открытое свойство, но, увы, нет.) В конце концов, решать вам, но метод 1 или 3 должен выполняйте работу достаточно хорошо ...

Надеюсь, это поможет.

3
ответ дан 5 December 2019 в 23:17
поделиться

Таким образом, данные представляют собой utf8 (кодировка по умолчанию для StreamReader). Это многобайтовая кодировка, поэтому IndexOf будет нежелательным. Вы можете:

Encoding.UTF8.GetByteCount(string)

на ваших данных, добавив 1 или 2 байта для конца отсутствующей строки.

1
ответ дан 5 December 2019 в 23:17
поделиться

Если вам нужно подсчитать байты, я бы пошел с BinaryReader. Вы можете взять результаты и привести их в соответствие с необходимостью, но я считаю, что его представление о его текущем положении более надежно (поскольку оно читает в двоичном виде, оно неуязвимо для проблем с набором символов).

1
ответ дан 5 December 2019 в 23:17
поделиться

Итак, ваша последняя строка содержит «ДАННЫЕ» + неизвестное количество байтов данных. Вы можете извлечь позицию, используя IndexOf () с вашей последней прочитанной строкой. Затем перенастройте поток. Положение.

Но я не уверен, стоит ли вообще использовать ReadLine () в этом случае. Возможно, было бы лучше читать побайтово, пока вы не достигнете отметки «DATA».

0
ответ дан 5 December 2019 в 23:17
поделиться

Разрывы строк легко идентифицируются без необходимости предварительного декодирования потока (за исключением некоторых кодировок, редко используемых для текстовых файлов, таких как EBCDIC, UTF-16, UTF-32), поэтому можно просто прочитать каждую строку как байты, а затем декодировать всю строку:

using (FileStream stream = File.OpenRead(path)) {
   List<byte> buffer = new List<byte>();
   bool hasCr = false;
   bool done = false;
   while (!done) {
      int b = stream.ReadByte();
      if (b == -1) throw new IOException("End of file reached in header.");
      if (b == 13) {
         hasCr = true;
      } else if (b == 10 && hasCr) {
         string line = Encoding.UTF8.GetString(buffer.ToArray(), 0, buffer.Count);
         if (line == "DATA") {
            done = true;
         } else {
            HandleHeaderLine(line);
         }
         buffer.Clear();
         hasCr = false;
      } else {
         if (hasCr) buffer.Add(13);
         hasCr = false;
         buffer.Add((byte)b);
      }
   }
   _dataOffset = stream.Position;
}

Вместо того, чтобы закрывать поток и открывать его снова,

0
ответ дан 5 December 2019 в 23:17
поделиться