C #: использование StreamReader для чтения строки из txt файла, но Peek () возвращает -1, даже если осталось много строк - PullRequest
3 голосов
/ 21 февраля 2012

Я использую метод Peek () StreamReader, чтобы проверить, нужно ли обрабатывать больше строк.В моем файле более 1000 строк, но Peek () неожиданно возвращает -1, когда достигает строки # 750.Я проверил, но, кажется, нет различий между строкой № 750 и № 751.Даже если я удалил строки 750 и 751, они все равно будут разбиты на другую строку.

Ниже приведены мои коды для вашей информации:

try
{
    String ftpserver = ftp + filename;
    reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpserver));
    reqFTP.UsePassive = false;
    reqFTP.UseBinary = true;
    reqFTP.Proxy = null;
    reqFTP.Credentials = new NetworkCredential(username, password);

    reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
    response = (FtpWebResponse)reqFTP.GetResponse();
    stream = response.GetResponseStream();
    reader = new StreamReader(stream, ConfigHelper.MyEncoding);
    while (reader.Peek() > -1)
    {
        string x = reader.ReadLine();
        if (x != null)
        {
          //.......
         }
    }
}
catch (Exception ex)
{
}
finally
{
    if (reader != null)
        reader.Close();
    if (response != null)
        response.Close();
}

Я пытался while ((x = reader.ReadLine()) != null), но исключение«Невозможно получить доступ к удаленному объекту» было выброшено.

Наконец я понял это с помощью: while (stream.CanRead && (x = reader.ReadLine()) != null)

Ответы [ 5 ]

8 голосов
/ 21 февраля 2012

Хотя не объясняет , что происходит, я бы лично не стал использовать Peek.Я бы использовал:

string line;
while ((line = reader.ReadLine()) != null)
{
    // Use the line
}

Таким образом, вы только читаете в одном месте.Это почему-то кажется более вменяемым, чем проверка, можете ли вы прочитать, а затем прочитать.

Вы также можете написать метод для создания IEnumerable<string> из TextReader (или изFunc<TextReader> (или имя файла), который может сделать все это более приятным.Если вы просто читаете файл и используете .NET 4, то File.ReadLines уже встроен.

РЕДАКТИРОВАТЬ: Вот одна из причин, по которой вы можете получить -1из документов StreamReader.Peek:

Целое число, представляющее следующий символ для чтения, или -1, если нет символов для чтения или если поток выполняетне поддерживает поиск.

Поддерживает ли ваш поток в поиске поддержки?

6 голосов
/ 21 февраля 2012

Я не уверен, почему Peek Method возвращает -1 в вашем случае, но обычный способ прочитать строки с StreamReader Class в конце файла - это многократновызывайте метод ReadLine , пока не будет возвращено null:

string line;
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line);
}
3 голосов
/ 21 февраля 2012

Вам нужно использовать Peek? Вы пропускаете определенные строки? Если вы хотите прочитать все строки, используйте это.

       while(!sr.EndOfStream)
            {
                //Do stuff
            }
0 голосов
/ 02 сентября 2016

Я столкнулся с подобной проблемой при попытке взаимодействия с приложением, которое требовало аутентификации. Peek () будет возвращать -1, когда встречаются с причудливыми символами (символы юникода?), А ReadLine () также ненадежен и в конечном итоге блокирует мое приложение, так как кажется, что стандартный поток процесса не был закрыт.

Использование метода Read () было единственным способом убедить меня, что я получил ВСЕ строки и символы. Кроме того, использование обработчиков событий ErrorDataReceived или OutputDataReceived также оказалось НЕОБХОДИМЫМ (пропущенные строки). Ниже показано, как я решил свою проблему и застраховал все строки и символы, которые были получены:

process.Start();
var stdOutput = process.StandardOutput;
StringBuilder fullMessage = new StringBuilder();
while (true)
{
    var character = (char)stdOutput.Read();
    fullMessage.Append(character);

    //Print Out All Characters
    Console.Write(character);
    if (fullMessage.ToString().EndsWith("Enter Password: "))
    {
        //Submit Password To Application
        using(StreamWriter writer = process.StandardInput){
            writer.Write("somepassword");
            writer.Flush();
        }

        break;
    }
}
0 голосов
/ 27 июня 2016

Как указано в MSDN, Peek Method не только возвращает -1 при достижении конца потока, но и в случае внутренних ошибок:

Peek методвозвращает целочисленное значение, чтобы определить, был ли конец файла, или произошла другая ошибка .Это позволяет пользователю сначала проверить, является ли возвращенное значение -1, прежде чем приводить его к типу Char.

Возможно, проверьте неправильные преобразования данных в вашей команде SQL, я думаю, этот метод тоже должен работать!

...