2009-06-14 3 views
1

레코드를 사용하여 이진 파일을 읽고 쓰고 싶은 파일이 있습니다. 처음에는 빈 파일이 있는데 새 레코드를 추가하고 싶습니다. 그러나 seekp 함수를 사용하면 위치는 (-1)입니다. 괜찮습니까? 체크 할 때 파일에 아무 것도 쓰지 않았 음을 알기 때문입니다. 코드를 참조하십시오 :C++의 오버플로 체인에서 fstream 파일 작업

void Library::addBook(Book newBook) 
{ 
fstream dataFile; 
dataFile.open("BookData.dat", ios::in | ios::out); 
    if (!dataFile) 
    { 
     cerr << "File could not be opened" << endl; 
    } 

int hashResult = newBook.getId() % 4 + 1; // The result of the hash function 

    // Find the right place to place the new book 
    dataFile.seekg((hashResult - 1) * sizeof(Book), ios::beg); 

    Book readBook; 
    dataFile.read(reinterpret_cast<char*>(&readBook), sizeof(Book)); 

    // The record doesnt exist or it has been deleted 
    if (readBook.getId() == -1) 
    { 
     // The record doesnt exist 
     if (readBook.getIdPtr() == -1) 
     { 
      dataFile.seekp((hashResult - 1) * sizeof(Book)); 
      dataFile.write(reinterpret_cast<char*>(&newBook), sizeof(Book)); 

     } 
     // The record has been deleted or there is already such record with such hash function 
     // so we need to follow the pointer to the overflow file 
     else 
     { 
      newBook.setIsBookInData(false); // New book is in overflow file 
      overflowFile.seekg((readBook.getIdPtr() - 1) * sizeof(Book)); 
      overflowFile.read(reinterpret_cast<char*>(&readBook), sizeof(Book)); 
      // Follow the chain 
      while (readBook.getIdPtr() != -1) 
      { 
       overflowFile.seekg((readBook.getIdPtr() - 1) * sizeof(Book)); 
       overflowFile.read(reinterpret_cast<char*>(&readBook), sizeof(Book)); 
      } 
      readBook.setIdPtr(header); // Make the pointer to point to the new book 
      overflowFile.seekp((header - 1) * sizeof(Book)); 
      overflowFile.write(reinterpret_cast<char*>(&newBook), sizeof(Book)); 
      header++; 
     } 
    } 

누군가가 내가 파일을 쓸 수없는 이유를 말해 줄 수 있다면 정말 그것을 appriciate 할 것입니다. 사전에

감사합니다,

그렉

+0

: (해결 방법을 모른다는 사람이 있습니까? –

+0

숙제가 아니라면 왜 직렬화가 필요한지'Boost.Serialization', 바이너리 데이터 교환을위한'Google Protocol Buffers ' 프로그램 (또는 XML 용 라이브러리, 텍스트 형식이 허용되는 경우 JSON), 경량 데이터베이스 솔루션 용 'sqlite'? – jfs

답변

2

자, 여기가 도움이 될 몇 가지 제안 사항 : 파일을 열 때

  • 이, ios_base를 사용 : 바이너리 플래그
  • 도서는 POD 있는지 (즉, C 호환 형)를 만들
  • 읽거나) 스트림 전과
  • 이 readBook.getId를 (사용하지 않는 후 유효한 상태에 있음을 쓸 때 == -1 읽기
  • 이 있는지 확인 성공 여부를 확인하는 것이 있는지 확인하십시오 때 당신은 당신이 g가 아닌 시내로 들어갑니다.
  • 파일을 찾을 때마다 버퍼를 사용하여 파일의 총 바이트 수를 확인한 다음이를 초과하지 않도록하십시오. 상대 검색을 수행 할 때마다
  • 을 사용하십시오 (ios_base :: 당신이 그 제안의에 대한 구체적인 질문이 있으면 알려 주시기 아마 우리가 더 나은 서비스를 안내 할 수 reinterpret cast<char*>

대 사용 static_cast<char*>(static_cast<void*>(&book))

  • ) 예를 들어 구걸.

  • 1

    당신은 분명히 파일의 끝을지나 읽고있다. seekg 호출은 아마도 끝까지 지나가는 읽기 포인터를 이동 한 다음 이라고 말하면이라고 읽습니다. 스트림이 실패 상태로 설정됩니다. 수행하여이 확인하십시오 전화를 읽을

    std::cout << dataFile.fail() << std::endl; 
    

    후.

    당신이하려는 레코드 관리의 종류는 간단한 작업이 아닙니다. 어쩌면 SQLite 같은 서버리스 DBE 또는 Boost.Serialization 같은 다른 직렬화 라이브러리를 사용해보아야합니다.

    또한 파일은 ios :: binary 플래그로 열어야합니다.