C ++ Ввод и вывод файла: невозможно ввести - PullRequest
1 голос
/ 27 марта 2012

Следующий код C ++ предназначен для чтения текстового файла, а затем записи количества символов в каждой строке и количества всех символов в текстовом файле. Я использую MS Visual Studio 2008. Но что-то не так.все символы вводятся в текстовые файлы, , но номера каждой строки не вводятся в текстовые файлы . Теперь я не могу понять это. Может кто-нибудь дать мне какой-нибудь совет? Большое спасибо!

И еще один вопрос: что мне сделать, чтобы вставить что-то в середину текстового файла?

Это мой код:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
fstream inOut("copy.txt",ios::in | ios::out | ios::app);

if (!inOut)
{
    cerr << "ERROR:cannot open file!" << endl;
    return -1;
}

int cnt = 0;
char ch;

inOut.seekg(0);

while(inOut.get(ch))
{
    cout.put(ch);
    ++cnt;
    if ('\n' == ch)
    {
        ios::pos_type mark = inOut.tellg();

        if (!inOut)
        {
            cerr << "ERROR!" << endl;
            return -1;
        }
        inOut << cnt;
        inOut.put(' ');

        inOut.seekg(mark);
    }
}
inOut.clear();
inOut << cnt << endl;
cout << "[" << cnt << "]" << endl;
}

Файл txt перед запуском: enter image description here

Файл txt после запуска: enter image description here

Результат в командной строке: enter image description here

Ответы [ 3 ]

2 голосов
/ 27 марта 2012

Я не очень хорошо знаю fstream, но я думаю, что вы хотите изменить способ, которым вы это делаете. Вы можете думать о файле как о непрерывной части памяти. Присоединение на конце легко, но вставка в середине может быть проблематичной. В частности, если вы вставите что-то, ваш seekg может быть недействительным.

Я бы порекомендовал три стратегии:

  1. Поймите, что происходит в настоящее время (попробуйте закрыть файл до seekg и посмотрите, не написано ли что-нибудь inOut << cnt;)
  2. Чтение из одного файла, запись в другой файл - это, скорее всего, будет более эффективным и менее сложным, чем попытка изменить файл на месте.
  3. Чтение из исходного файла, сохранение и изменение в памяти, запись измененного буфера в исходный файл. Для больших файлов это может быть менее эффективно, чем # 2, но это означает, что вам не нужно два файла на диске.
1 голос
/ 27 марта 2012
    #include <iostream>
    #include <fstream>

using namespace std;

int main()
{
fstream inOut("copy.txt",ios::in | ios::out | ios::app);

if (!inOut)
{
    cerr << "ERROR:cannot open file!" << endl;
    return -1;
}

int cnt = 0;
int cntline=0;
char ch;

inOut.seekg(0);

while(inOut.get(ch))
{
    cout.put(ch);
    //++cnt         it include '\n' it  should put behind of "if"
    if ('\n' == ch)
    {   ios::pos_type mark = inOut.tellg();

        if (!inOut)
        {
            cerr << "ERROR!" << endl;
            return -1;
        }
        cntline=cnt-cntline;        //add it to account the number of chars of each line
        inOut.seekg(0,ios::end);   //here!!!!!!!!!!!!!!!!!!!!!!!!!!!  add this , the resault is finally right!  the reason it's down here.
        inOut << cntline;
        cntline=cnt;                // and here! it can assure the number of the chars of each line be right!
        inOut.put(' ');
        inOut.seekg(mark);
    }
    else
    {
        ++cnt;  //   it's here!
    }
}
inOut.clear();
inOut << cnt << endl;
cout << "[" << cnt << "]" << endl;
}

inOut.seekg (0, ИОС :: конец)
я не уверен, но вы можете взять это как справку.

вы открываете файл с помощью «ios :: app», поэтому VS 2008 позволяет добавлять только текст , начиная с конца файла (в vc 6.0 этого не произойдет).

, если файл:

  1. компилируется
  2. против 2008

при получении первого '\ n' указатель файла указывает на 'vs 2008' (да, точно так же, как общий указатель указывает на строку). и я отлаживаю его, затем нахожу значение объекта потока с именем _Wrotesome .its значение false! так что я думаю, что компилятор считает, что указатель файла указывает на постоянное sting.so, вы просто не можете ничего написать в этой позиции. поэтому я добавляю код inOut.seekg (0, ios :: end); . теперь вы можете написать что угодно в этот текст!

желаю, чтобы это помогло вам!

0 голосов
/ 27 марта 2012

Я не знаю, почему вы выбираете std :: fstream в качестве инструмента. Если std :: fstream не запрашивается или не требуется, я хотел бы привести пример для решения вашей проблемы. Вот некоторые ограничения:

а. Я прочитал весь файл в память за одну операцию ReadFile. Если ваш файл большой, вы можете заменить его циклом. б. Я полагаю, ваш разделитель строк '\ n'. с. Я добавляю [line_count] перед '\ n', что выглядит лучше.

вот мой код.

#include "windows.h"
#include "sstream"

int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = ::CreateFile(L"C:\\Users\\wujian\\Desktop\\pingback - Copy.log", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE )
{
    DWORD dwSize = ::GetFileSize(hFile, NULL);
    if (dwSize)
    {
        char *pBuffer = new char[dwSize];
        DWORD dwRead = 0;
        ::ReadFile(hFile, pBuffer, dwSize, &dwRead, NULL);
        if (dwRead == dwSize)
        {
            std::stringstream ss;
                    int iPos = 0;
            int iLine = 0;
            while (iPos < dwSize)
            {
                if (pBuffer[iPos] == '\n')
                {
                    ss << '[' << iLine << ']';
                    iLine = 0;
                }
                ss << pBuffer[iPos];
                iPos ++, iLine ++;
            }
            ss << '[' << dwSize << ']';
            ::SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
            DWORD dwWrite = 0;
            ::WriteFile(hFile, ss.str().c_str(), ss.str().length(), &dwWrite, NULL;
            }
            ::CloseHandle(hFile);
        }
    }
    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...