Mr.J Temat założony przez niniejszego użytkownika |
[C++, fstream] Jednoczesne wczytywanie i zapisywanie danych w pliku » 2013-11-24 20:12:41 Witam, przeczytalem na pewnej stronie ze mozliwe jest przeprowadzenie jednoczesnie operacji zapisu/wczytania danych z/do pliku otwierajac go w ten sposob: ... std::fstream mapData; mapData.open(( "Maps/" + mapName + ".Pg" ).c_str(), std::ios::binary | std::ios::in | std::ios::out ); ...
...jednak wydaje mi sie ze wtedy funkcja read nie pobiera zadnych danych. Oto caly kod: int MapManager::save_sector( int sector_x, int sector_y, int offset_x, int offset_y ) { if( sector_x >= 0 && sector_x < number_of_x_sectors && sector_y >= 0 && sector_y < number_of_y_sectors ) { std::fstream mapData; mapData.open(( "Maps/" + mapName + ".Pg" ).c_str(), std::ios::binary | std::ios::in | std::ios::out ); if( !mapData ) { return - 1; } mapData.seekg( 0, mapData.end ); long length = mapData.tellg(); mapData.seekg( 0, mapData.beg ); char * buffer = new char[ length ]; mapData.read( buffer, length ); long g_possition = 0; int mapData_size = 0; mapData.read(( char * ) & mapData_size, sizeof( int ) ); g_possition += sizeof( int ) + mapData_size; mapData.seekg( g_possition ); long sector_size = 0; for( int i_sector = 0; i_sector < sector_y * number_of_x_sectors + sector_x; i_sector++ ) { if( g_possition + 3 >= length ) return - 11; mapData.read(( char * ) & sector_size, sizeof( long ) ); g_possition += sizeof( long ) + sector_size; mapData.seekg( g_possition ); } flag_Set tempFlag = { 1, 1, 1, 1, 0 }; signed int tempID = - 1; std::vector < OBJinfo > tempInfo; int square_size = 0; char empty_info = 'E'; long temp_g = g_possition; g_possition += sizeof( long ); mapData.seekp( g_possition ); for( int iPlane = 0; iPlane < 2; iPlane++ ) { for( int i = 0; i < TILES_PER_SECTOR; i++ ) { for( int j = 0; j < TILES_PER_SECTOR; j++ ) { tempID = objSlot[ iPlane ][ i + offset_y ][ j + offset_x ].get_ID(); tempInfo = objSlot[ iPlane ][ i + offset_y ][ j + offset_x ].get_info(); if( tempInfo.size() > 0 ) { square_size = 24 + sizeof( tempInfo.at( 0 ) ); } else square_size =( sizeof( int ) * 6 + sizeof( char ) ); mapData.write(( char * ) & square_size, sizeof( int ) ); mapData.write(( char * ) & tempFlag, sizeof( int ) * 5 ); if( i == 0 && j == 0 && iPlane == 0 ) { int test_int = 5; mapData.seekg( g_possition + sizeof( int ) ); mapData.read(( char * ) & test_int, sizeof( int ) ); std::ofstream test1; test1.open( "test zmiennej.txt" ); test1 << test_int; test1.close(); } mapData.write(( char * ) & tempID, sizeof( int ) ); if( tempInfo.size() > 0 ) mapData.write(( char * ) & tempInfo[ 0 ], sizeof( tempInfo[ 0 ] ) ); else mapData.write(( char * ) & empty_info, sizeof( char ) ); sector_size +=( sizeof( int ) + square_size ); } } } mapData.seekp( temp_g ); mapData.write(( char * ) & sector_size, sizeof( long ) ); g_possition += sector_size; mapData.seekp( g_possition ); mapData.write(( char * ) & buffer[ g_possition ], length - g_possition ); delete[] buffer; buffer = NULL; mapData.close(); } return 0; }
Dodam jeszcze ze calosc sie kompiluje ale w grze wyglada to tak ze po "aktualizacji" sektorow wszystko wraca do wartosci poczatkowych czyli nic nie zostaje zapisane :/ PS. Zapomnialem dodac ze wiem ze miejsca gdzie pojawia sie vector<OBJinfo> sa blednie napisane, ale moj program nie obsluguje w tej chwili tych przypadkow wiec nie stanowia one problemu i nie pokusilem sie o ich poprawienie :P |
|
DejaVu |
» 2013-11-27 03:56:07 Napisz prostszy program do przetestowania 'jednoczesnego' odczytu i zapisu do pliku. Chociażby coś podobnego do tego: char tablica[ 50 ] = "abc"; plik.write( tablica, 3 ); plik.read( tablica + 3, 3 ); tablica[ 6 ] = 0;
N-lat temu też próbowałem jednoczesny odczyt i zapis do pliku na fstream-ie i jakoś mi wtedy nie wychodziło. Napisz maksymalnie krótki program weryfikujący Twoje pytanie, wklej go i podziel się swoimi obserwacjami. Być może wówczas ktoś zweryfikuje poprawność Twojego rozwiązania i da Ci ostateczną odpowiedź, popartą np. dokumentacją, standardem czy też większym doświadczeniem. |
|
Mr.J Temat założony przez niniejszego użytkownika |
» 2013-11-27 10:11:42 Witam, wczoraj udalo mi sie wreszcie rozwiazac problem, na moje szczescie bylem na tyle zdesperowany ze probowalem wszystkiego...okazalo sie ze (nie do konca rozumiem czemu) w przypadku fstream'a trzeba uzywac jednoczesnie funkcji seekg i seekp niezaleznie od tego czy wczytujemy czy zapisujemy. Po wstawieniu tych dwoch funkcji jednoczesnie obok siebie wszystko zaczelo dzialac(musialem tez usunac ten fragment testujacy tamta zmienna). Dodam jeszcze ze po uruchomieniu gry dotralo do mnie ze cala operacja kopiowania danych do bufora jest zbedna, bo jedynie podmieniam fragmenty danych, a nie tworze plik od nowa. Calosc wyglada tak: (Komentarze moga byc troche mylace dlatego nie nalezy zwracac na nie uwagi.) int MapManager::save_sector( int sector_x, int sector_y, int offset_x, int offset_y, bool underground ) { if( sector_x >= 0 && sector_x < number_of_x_sectors && sector_y >= 0 && sector_y < number_of_y_sectors ) { std::fstream mapData; mapData.open(( "Maps/" + mapName + ".Pg" ).c_str(), std::ios::binary | std::ios::in | std::ios::out ); if( !mapData ) { return - 1; } mapData.seekg( 0, mapData.end ); long length = mapData.tellg(); mapData.seekg( 0, mapData.beg ); long g_possition = 0; int mapData_size = 0; mapData.seekp( 0 ); mapData.read(( char * ) & mapData_size, sizeof( int ) ); g_possition += sizeof( int ) + mapData_size; mapData.seekg( g_possition ); mapData.seekp( g_possition ); long sector_size = 0; long Underground_surfaceSize = 0; long surfaceSize = 0; for( int i_sector = 0; i_sector < sector_y * number_of_x_sectors + sector_x; i_sector++ ) { if( g_possition + 3 >= length ) return - 11; mapData.read(( char * ) & sector_size, sizeof( long ) ); if( sector_size < 59392 || sector_size > 100000 ) { std::ofstream test2; test2.open( "test rozmiaru sektora.txt" ); test2 << sector_size; test2.close(); return - 33; } g_possition += sizeof( long ) + sector_size; mapData.seekg( g_possition ); mapData.seekp( g_possition ); } long temp_g_for_sector_size = 0; long temp_g_for_surface_size = 0; temp_g_for_sector_size = g_possition; g_possition += sizeof( long ); if( underground == true ) temp_g_for_surface_size = g_possition; mapData.seekg( g_possition ); mapData.seekp( g_possition ); mapData.read(( char * ) & Underground_surfaceSize, sizeof( long ) ); g_possition += sizeof( long ) + Underground_surfaceSize; if( underground == false ) temp_g_for_surface_size = g_possition; mapData.seekg( g_possition ); mapData.seekp( g_possition ); mapData.read(( char * ) & surfaceSize, sizeof( long ) ); mapData.seekg( temp_g_for_surface_size + sizeof( long ) ); mapData.seekp( temp_g_for_surface_size + sizeof( long ) ); flag_Set tempFlag = { 1, 1, 1, 1, 0 }; signed int tempID = - 1; std::vector < OBJinfo > tempInfo; int square_size = 0; char empty_info = 'E'; int iPlane = 0; if( underground == false ) iPlane = 1; sector_size = 0; long newSurfaceSize = 0; for( int i = 0; i < TILES_PER_SECTOR; i++ ) { for( int j = 0; j < TILES_PER_SECTOR; j++ ) { tempFlag = myTile[ iPlane ][ i + offset_y ][ j + offset_x ].get_flag(); tempID = objSlot[ iPlane ][ i + offset_y ][ j + offset_x ].get_ID(); tempInfo = objSlot[ iPlane ][ i + offset_y ][ j + offset_x ].get_info(); if( tempInfo.size() > 0 ) { square_size = 24 + sizeof( tempInfo.at( 0 ) ); } else square_size =( sizeof( int ) * 6 + sizeof( char ) ); mapData.write(( char * ) & square_size, sizeof( int ) ); mapData.write(( char * ) & tempFlag, sizeof( int ) * 5 ); mapData.write(( char * ) & tempID, sizeof( int ) ); if( tempInfo.size() > 0 ) mapData.write(( char * ) & tempInfo[ 0 ], sizeof( tempInfo[ 0 ] ) ); else mapData.write(( char * ) & empty_info, sizeof( char ) ); newSurfaceSize +=( sizeof( square_size ) + square_size ); } } if( underground == true ) { sector_size =( sizeof( long ) * 2 + newSurfaceSize + surfaceSize ); } else { sector_size =( sizeof( long ) * 2 + newSurfaceSize + Underground_surfaceSize ); } mapData.seekp( temp_g_for_surface_size ); mapData.seekg( temp_g_for_surface_size ); mapData.write(( char * ) & newSurfaceSize, sizeof( long ) ); mapData.seekp( temp_g_for_sector_size ); mapData.seekg( temp_g_for_sector_size ); mapData.write(( char * ) & sector_size, sizeof( long ) ); mapData.close(); } return 0; }
Troche zaluje, ze nie zatytulowalem tego tematu np: "Problem z jednoczesnym zapisem i wczytywaniem danych za pomoca fstream" bo w obecnej postaci moze okazac sie malo pomocny dla kogos innego :/ Zastanawia mnie tez w jaki sposob rozwiazuje sie problem roznego rozmiaru zmiennych na roznych maszynach, bo co jezeli ktos ma na komputerze zmienna int zajmujaca 8bajtow ? W jaki sposob poprawnie odczytac takie dane mapy? Jest jakis sposob rzutowania 4 bajtowej int na 8 bajtowa? |
|
pekfos |
» 2013-11-27 13:12:47 Troche zaluje, ze nie zatytulowalem tego tematu np: "Problem z jednoczesnym zapisem i wczytywaniem danych za pomoca fstream" bo w obecnej postaci moze okazac sie malo pomocny dla kogos innego :/ |
To popraw? Zastanawia mnie tez w jaki sposob rozwiazuje sie problem roznego rozmiaru zmiennych na roznych maszynach, bo co jezeli ktos ma na komputerze zmienna int zajmujaca 8bajtow ? |
Można używać typów, których rozmiar jest stały ( <cstdint>) |
|
« 1 » |