2016-05-06 4 views
0

У меня есть задача скопировать элементы из файла .txt [файл прямого доступа] в .bin файл [файл фиксированной длины записи] (домашняя работа). .txt файл содержит строки. Каждая строка имеет одно слово. Я придумал код ниже, но я не уверен, что это то, что нужно и даже немного правильное. Любая помощь будет полезна! (Я новичок в C++)C++ Из текстового файла в двоичный файл

#include <iostream> 
#include <fstream> 
#include <string> 
using namespace std; 
const int buffer_size = 30; 

class Word{ 
    char name[buffer_size]; 
public: 
    void setName() // Trying to get every word from a line 
    { 
     string STRING; 
     ifstream infile; 
     infile.open ("text.txt"); 
     while(!infile.eof()) // To get you all the lines. 
     { 
      getline(infile,STRING); // Saves the line in STRING. 
     } 
     infile.close(); 
    } 
}; 


void write_record() 
{ 
    ofstream outFile; 
    outFile.open("binFILE.bin", ios::binary | ios::app); 
    Word obj; 
    obj.setName(); 
    outFile.write((char*)&obj, sizeof(obj)); 
    outFile.close(); 
} 


int main() 
{ 
    write_record(); 
    return 0; 
} 

НОВЫЙ ПОДХОД:

class Word 
{ 
char name[buffer_size]; 
public: 
    Word(string = ""); 
    void setName (string); 
    string getName() const; 
}; 

    void readWriteToFile(){ 
     // Read .txt file content and write into .bin file 
     string temp; 
     Word object; 
     ofstream outFile("out.dat", ios::binary); 
     fstream fin ("text.txt", ios::in); 
     getline(fin, temp); 
     while(fin) 
     { 
      object.setName(temp); 
      outFile.write(reinterpret_cast< const char* >(&object),sizeof(Word)); 
      getline(fin, temp); 
     } 
     fin.close(); 
     outFile.close(); 
} 

int main() 
{ 
readWriteToFile(); 


return 0; 
} 
Word::Word(string nameValue) 
{ 
setName(nameValue); 
} 
void Word::setName(string nameString) 
{ 
// Max 30 char copy 
const char *nameValue = nameString.data(); 
int len = strlen(nameValue); 
len = (len < 31 ? len : 30); 
strncpy(name, nameValue, len); 
name[len] = '\0'; 
} 
string Word::getName() const 
{ 

возвращение имя; }

+2

Возможно, вам будет интересно прочитать ["Почему iostream :: eof внутри условия цикла считается неправильным?"] (Http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop -условию рассмотренный-неправильно). –

+0

Предложение: Если вам разрешено использовать 'std :: string' для этого назначения вместо этого:' char name [buffer_size]; 'сделайте это. Спасите вас от боли. Да. Много боли. – user4581301

+0

@JoachimPileborg Спасибо за совет. Я все еще ищу ответ на мой вопрос! Дайте мне знать, если у вас есть идея :) – Maartin1996

ответ

0

Быстрый комментарий и пройти через

#include <iostream> 
#include <fstream> 
#include <string> 
using namespace std; 

using namespace std; Избегайте в то время как вы учитесь. Это может привести к некоторым действительно мерзким и жестким ошибкам, поскольку ваши функции могут быть заменены на функции с тем же именем в стандартной библиотеке.

const int buffer_size = 30; 

class Word 
{ 
    char name[buffer_size]; 

Так это выглядит, как вам разрешено использовать std::string почему бы не использовать его здесь?

public: 
    void setName() // Trying to get every word from a line 

Действительно плохое имя для функции, по-видимому, предполагается // Trying to get every word from a line

{ 
     string STRING; 
     ifstream infile; 
     infile.open("text.txt"); 
     while (!infile.eof()) // To get you all the lines. 
     { 
      getline(infile, STRING); // Saves the line in STRING. 
     } 

Несколько вещей здесь не так. Один из них - эпический Why is iostream::eof inside a loop condition considered wrong?

Далее, пока код читает каждую строку, он ничего не делает с линией. STRING никогда не хранится нигде.

Наконец, в классе, который звучит так, как будто он должен содержать и управлять одним словом, он читает все слова в файле. Может возникнуть случай превращения этой функции в статическую фабрику, которая производит std::vectorWords.

 infile.close(); 
    } 
}; 

void write_record() 
{ 
    ofstream outFile; 
    outFile.open("binFILE.bin", ios::binary | ios::app); 

ios::app будет добавлен в существующий файл. Это не похоже на то, что описано в описании назначения.

Word obj; 
    obj.setName(); 

Мы уже coverred немощи Word класса.

outFile.write((char*) &obj, sizeof(obj)); 

Сбрасывание объекта в поток без определения протокола данных или использование любой сериализации опасно. Это делает файл не переносным. Вы обнаружите, что некоторые классы, vector и string видные среди них, не содержат их данных. Запись строки в файл может дать вам не что иное, как счетчик и адрес, который почти наверняка недействителен при загрузке файла.

В этом случае весь объект содержит массив символов, который должен записываться в файл чисто, но он всегда будет писать ровно 30 байт, и это может быть не то, что вы хотите.

outFile.close(); 
} 

int main() 
{ 
    write_record(); 
    return 0; 
} 

Поскольку это домашнее задание я не пишу эту присоску для вас, но вот несколько советов:

Read file line by line поможет вам начать работу на читателя файла. Ваш случай проще, потому что в каждой строке есть только одно слово. Ваш учитель может бросить Curveball и добавить больше материала на линию, так что вы можете проверить на это.

Прочтите слова из файла в файл std::vector. vector сделает вашу работу настолько легкой, что у вас может быть время для других домашних заданий.

Очень упрощенно реализация:

std::vector<std::string> words; 
while (getline(infile, STRING)) // To get you all the lines. 
{ 
    words.push_back(STRING); 
} 

Для записи файла обратно в двоичный, I suggest going Pascal style. Сначала записать длину строки в двоичном виде. Use a known, fixed width unsigned integer (нет такой вещи как отрицательная строка) и watch out for endian. Как только длина будет записана, напишите только количество символов, которые вам нужно записать.

Игнорирование Endian, вы должны иметь что-то вроде этого:

uint32_t length = word.length(); // length will always be 32 bits 
out.write((char*)&length, sizeof(length)); 
out.write(word.c_str(), length); 

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

+0

Я взял под ваши советы. Кроме того, я пробовал использовать другой подход. Поскольку я на Linux, я не знаю, как открыть мой .bin-файл, чтобы я мог видеть содержимое файла (не уверен, что моя программа теперь работает, но, может быть, вы можете взглянуть) – Maartin1996

+0

Сделайте поиск с любым менеджером пакетов, который использует ваш дистрибутив Linux для «шестнадцатеричного редактора», или проверьте, содержит ли ваш любимый текстовый редактор шестнадцатеричный режим. Шестигранный редактор позволит вам открыть файл и увидеть его в виде байтов. – user4581301

Смежные вопросы