TFileStream dopisanie do poczatku pliku

dział ogólny

TFileStream dopisanie do poczatku pliku

Nowy postprzez ch2_lbn » środa, 24 marca 2010, 20:11

Witam
Pisze pod C++ Builder 2007
mam spory problem aby dopisac dane do pliku ale nie na jego koniec tylko na poczatek np:
Zawartosc pliku przed "9987"
Dodanie do pliku "12"
Dodanie do pliku "34"
Zawartosc pliku po "34129987"

Z dopisywaniem na konicu pliku nie ma problemu
Kod: Zaznacz cały
plik->Seek(plik->Size,soFromBeginning);
plik->Write(dana.c_str(),dana.Length());


A po zmianie na
Kod: Zaznacz cały
plik->Seek(0,soFromBeginning);
plik->Write(dana.c_str(),dana.Length());

Nadpisuje mi istniejace dane.

Nie wiem juz czy jest to mozliwe przeszukalem chyba caluskie google. Dodam ze zalezy mi na uzyciu TFileStream bo juz je mniejwiecej zrozumialem.

I mam jeszcze ogolne pytanie w jakis posob wczytywac duzy plik (powyzej 100MB) gdzy bede wykonywal dzialania po czesciach czyli np: na pierwszych 10-ciu znakach beda wykonywane dzialania i beda one zapisane do nowego pliku(nowy.txt) i kolejne 10 znakow i nastepne dzialania na nich i wynik bedzie dopisany na poczatek pliku (nowy.txt)

Z gory dzieki za odpowiedzi i sugestie choc bardzo bym prosil o kawalki kodu poniewaz jestem poczatkujacym.
Avatar użytkownika
ch2_lbn
 
    Windows 7Firefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez Cyfrowy Baron » środa, 24 marca 2010, 20:34

A tak:

Kod: Zaznacz cały
    plik->Position = 0;
    plik->Write(dana.c_str(), dana.Length());
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez Cyfrowy Baron » środa, 24 marca 2010, 20:42

To nie zadziała, gdyż potrzebna byłaby funkcja typu Insert a tej klasa TFileStream nie posiada. Utwórz obiekt klasy TMemoryStream, zapisz do niego to co chcesz dopisać do pliku na początku, potem dopisz do tego zawartość pliku, na końcu przepisz wszystko do obiektu klasy TFileStream i zapisz do pliku, albo od razu zapisz zawartość klasy TMemoryStream do pliku. Podobnie możesz postąpić z klasą TFileStream.

Zamiast na zmiennych typu AnsiString operuj raczej na char.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez ch2_lbn » środa, 24 marca 2010, 20:48

Cyfrowy Baron napisał(a):To nie zadziała, gdyż potrzebna byłaby funkcja typu Insert a tej klasa TFileStream nie posiada. Utwórz obiekt klasy TMemoryStream, zapisz do niego to co chcesz dopisać do pliku na początku, potem dopisz do tego zawartość pliku, na końcu przepisz wszystko do obiektu klasy TFileStream i zapisz do pliku, albo od razu zapisz zawartość klasy TMemoryStream do pliku. Podobnie możesz postąpić z klasą TFileStream.

Zamiast na zmiennych typu AnsiString operuj raczej na char.


A taka operacja nie bedzie uciazliwa gdy bede bazowal na plikach powyzej 100MB (majac na mysli pliki ok 1 GB :) )
Avatar użytkownika
ch2_lbn
 
    Windows 7Firefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez Cyfrowy Baron » czwartek, 25 marca 2010, 08:14

Będzie uciążliwa gdyż trzeba będzie wszystko kopiować i przepisywać. Spróbuj tak jak kombinowałeś z TFileStream, ale zamiast funkcji Write użyj WriteBuffer:

Kod: Zaznacz cały
void __fastcall WriteBuffer(const void * Buffer, int Count); 


W pliku pomocy dla tej funkcji jest napisane:

Writes Count bytes from Buffer onto the stream and advances the current position of the stream by Count bytes.



Funkcja WriteBuffer jest dziedziczona po klasie TStream.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez polymorphism » czwartek, 25 marca 2010, 10:09

Nie wiem co miałoby zmienić zastosowanie WriteBuffer w przypadku strumieni plikowych/pamięciowych, jeśli:

    All the other data-writing methods of a stream (WriteBuffer, WriteComponent) call Write to do their actual writing.
Zastosowanie tej funkcji ma sens w przypadku strumieni takich jak TWinSocketStream, gdzie Read/Write nie daje gwarancji odebrania/wysłania żądanej ilości bajtów. Użycie ReadBuffer/WriteBuffer taką pewność daje.


@ch2_lbn, napisz do czego konkretnie jest Ci potrzebne to dopisywanie na początku.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez Cyfrowy Baron » czwartek, 25 marca 2010, 10:20

Nie będę się spierał co do WriteBuffer, gdyż nie testowałem, a z opisów tej funkcji wynika, że należy ją stosować przy zapisywaniu np. struktur do strumienia. Sugerowałem się tym opisem z pliku pomocy:


Writes Count bytes from Buffer onto the stream and advances the current position of the stream by Count bytes.



ale być może źle to rozumiem.



polymorphism napisał(a):@ch2_lbn, napisz do czego konkretnie jest Ci potrzebne to dopisywanie na początku.

Chyba ja mogę Tobie odpowiedzieć. Chodzi o dopisanie wartości typu AnsiString na początku dużego pliku rzędu 100 MB - 1 GB, czyli bez wczytywania i przetwarzania całego pliku. Problem polega na tym, że funkcja Write nie wstawia danych na początku pliku, lecz zastępuje dane. Ponieważ w przykładzie @ch2_lbn operuje na zmiennej AnsiString:

@ch2_lbn napisał(a):
Kod: Zaznacz cały
plik->Write(dana.c_str(),dana.Length());

chce więc pewnie dopisać na początku pliku jakieś dane tekstowe.

Gdyby klasa TFileStream posiadała funkcję Insert to o takie dopisanie właśnie by chodziło.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez polymorphism » czwartek, 25 marca 2010, 10:50

Sugerowałem się tym opisem z pliku pomocy:

To samo masz o Write:

    After writing to the resource, Write advances the current position by the number bytes written, and returns the number of bytes written.

(...) a z opisów tej funkcji wynika, że należy ją stosować przy zapisywaniu np. struktur do strumienia.

Tak, ale w przypadku, o którym pisałem wcześniej. W przeciwnym wypadku obie funkcje robią dokładnie to samo, zatem zaproponowanie WriteBuffer w żaden sposób nie przybliża do rozwiązania.

Ale żeby nie było, użycie WriteBuffer jest preferowane, jeśli piszemy bardziej ogólnie, wykorzystując strumień TStream.



Chyba ja mogę Tobie odpowiedzieć. (...)

Tyle to ja już z pierwszego posta zrozumiałem. Chodziło mi o konkretne zastosowanie, bo być może nie trzeba nic dopisywać na początku, może jest jakaś inna, optymalniejsza metoda.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez ch2_lbn » czwartek, 25 marca 2010, 15:38

polymorphism napisał(a):Nie wiem co miałoby zmienić zastosowanie WriteBuffer w przypadku strumieni plikowych/pamięciowych, jeśli:

    All the other data-writing methods of a stream (WriteBuffer, WriteComponent) call Write to do their actual writing.
Zastosowanie tej funkcji ma sens w przypadku strumieni takich jak TWinSocketStream, gdzie Read/Write nie daje gwarancji odebrania/wysłania żądanej ilości bajtów. Użycie ReadBuffer/WriteBuffer taką pewność daje.


@ch2_lbn, napisz do czego konkretnie jest Ci potrzebne to dopisywanie na początku.


To by mialo sluzyc cos jak kompresowanie i nie bardzo moglbym inaczej to robic niz dopisywanie na poczatku.
poniewaz bedzie kompresowac od poczatku pliku i czesciami gdzie w przypadku dekopresji bedzie potrzebne mi dopisywanie do pliku NA POCZATKU pliku
dodam ze dopisywanie bedzie bardzo czesto wystepowac dlatego nie mogl bym zbytnio dodawac jako string nowedane+staredane i zapis do pliku.

Chociaz chwila jezeli uzyje opcji read do czytania danych od konca pliku czyli np 10 ostatnich danych i wynik zapisze normalnie do pliku i kolejne bede dopisywal do pliku to chyba powinno miec taki efekt jaki bym chcial ?? tzn ze przy dekodowaniu bede wczytywal dane znowu od konca pliku co mi da cos takiego:

orginalny 123456789 (czytanie od konca)

skompresowany 987654321 (zapis od poczatku+czytanie od konca)
dekompresowany 123456789 (zapis od poczatku)

tylko problem gdy bede chcial brac po dwa znaki badz jak wspomnialem po 10
skompresowany 896745231 (zapis od poczatku+czytanie od konca)
dekompresowany 315274968 (zapis od poczatku)
wtedy nie wyjdzie to co mialo wyjsc :/

chyba ze wczytywac po 1 znaku od konca w for po 10 ?? czyli 10 ostatnich zankow czytajac od prawej do lewej

juz sam nie wiem :(
Avatar użytkownika
ch2_lbn
 
    Windows 7Firefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez Cyfrowy Baron » czwartek, 25 marca 2010, 17:03

Nie wiem co Ty kombinujesz, ale z kompresja to chyba nie ma nic wspólnego. Z Twojego wywodu wnioskuję, że chcesz szyfrować pliki. Co do tego strumieniowego dopisywania na początku pliku, to jest to chyba niemożliwe, gdyż w dopisywanym pliku wszystkie bity musiały by zostać przesunięte o długość dopisywanego tekstu, czyli cały plik wymagałby przetworzenia.

Jedyne co w kwestii dopisywania mogę zaproponować, to metodę polegającą na kopiowaniu:

Kod: Zaznacz cały

 TMemoryStream 
*File1 = new TMemoryStream;
 String tekst = "Cyfrowy Baron";
 File1->Write(tekst.c_str(), tekst.Length());

 TFileStream *File2 = new TFileStream("f:\\film.avi", fmOpenRead);

 File1->Seek(File1->Size, soFromBeginning);
 File1->CopyFrom(File2, File2->Size);

 delete File2;
 File1->SaveToFile("f:\\film.avi");
 delete File1;
 


albo z zachowaniem oryginalnego pliku:

Kod: Zaznacz cały

 TFileStream 
*File1 = new TFileStream("f:\\temp.dat", fmCreate);
 String tekst = "Cyfrowy Baron";
 File1->Write(tekst.c_str(), tekst.Length());

 TFileStream *File2 = new TFileStream("f:\\film.avi", fmOpenRead);

 File1->Seek(File1->Size, soFromBeginning);
 File1->CopyFrom(File2, File2->Size);

 delete File2;
 




Nie wiem jakiego rodzaju plik chcesz szyfrować, ale w przypadku niektórych plików wystarczyło by zmienić nagłówek pliku na dowolny ciąg znaków, by program obsługujący dany typ pliku nie był w stanie go otworzyć. Gdybyś chciał odkodować plik wystarczyło by ponownie przywrócić nagłówek pliku. Dla przykładu plik AVI ma na początku ciąg znaków RIFF. Zamiana tego ciągu znaków np. na spacje sprawi, że program multimedialny nie będzie w stanie go uruchomić. Przywrócenie właściwego ciągu znaków uczyni ten plik znów czytelnym:

kodowanie:
Kod: Zaznacz cały

 TFileStream 
*File2 = new TFileStream("f:\\film.avi", fmOpenWrite);
 File2->Position = 0;
 File2->Write("    ", 4);

 delete File2; 


dekodowanie:
Kod: Zaznacz cały

 TFileStream 
*File2 = new TFileStream("f:\\film.avi", fmOpenWrite);
 File2->Position = 0;
 File2->Write("RIFF", 4);

 delete File2; 


To taki prosty przykład, gdyż nie wiem dokładnie o co Tobie chodzi.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez polymorphism » czwartek, 25 marca 2010, 17:34

To by mialo sluzyc cos jak kompresowanie i nie bardzo moglbym inaczej to robic niz dopisywanie na poczatku.
poniewaz bedzie kompresowac od poczatku pliku i czesciami gdzie w przypadku dekopresji bedzie potrzebne mi dopisywanie do pliku NA POCZATKU pliku

Żeś to tak objaśnił, że w ogóle nie wiadomo o co tu chodzi :roll: No ale jeśli już koniecznie musisz to dopisywać na początku, to inaczej niż przepisując cały plik tego nie zrobisz. Choć z tego, co napisałeś, wynika, że nie będzie to optymalne rozwiązanie. Więc może postaraj się opisać problem dokładniej i czytelniej, podając zastosowanie tego, bo być może z góry przyjąłeś dziwaczne założenie, którego, co tu dużo mówić, nie da się w prosty a zarazem optymalny sposób obejść.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: TFileStream dopisanie do poczatku pliku

Nowy postprzez ch2_lbn » czwartek, 25 marca 2010, 18:27

Cyfrowy Baron napisał(a):Nie wiem jakiego rodzaju plik chcesz szyfrować, ale w przypadku niektórych plików wystarczyło by zmienić nagłówek pliku na dowolny ciąg znaków...

co do tego sposobu nie byl by to najlepszy sposob szyfrawania plikow poniewaz sa programy naprawcze i z taka zmiana naglowka szybko by sobie poradzily nawet w znacznym stopniu calego kodu.
ale do rzeczy nie do tego mi to jest przydatne tylko do kompresji (zmniejszania objetosci pliku)

polymorphism napisał(a):
To by mialo sluzyc cos jak kompresowanie i nie bardzo moglbym inaczej to robic niz dopisywanie na poczatku.
poniewaz bedzie kompresowac od poczatku pliku i czesciami gdzie w przypadku dekopresji bedzie potrzebne mi dopisywanie do pliku NA POCZATKU pliku

Żeś to tak objaśnił, że w ogóle nie wiadomo o co tu chodzi :roll: No ale jeśli już koniecznie musisz to dopisywać na początku, to inaczej niż przepisując cały plik tego nie zrobisz. Choć z tego, co napisałeś, wynika, że nie będzie to optymalne rozwiązanie. Więc może postaraj się opisać problem dokładniej i czytelniej, podając zastosowanie tego, bo być może z góry przyjąłeś dziwaczne założenie, którego, co tu dużo mówić, nie da się w prosty a zarazem optymalny sposób obejść.


mysle ze znalazlem rozwiazanie tak jak wspominalem iz bede czytal plik od konca znak po znaku (piszac prosciej od prawej do lewej).
Wiem ze niestety nie mozeczie mnie zrozumiec bo podalem malo szczegolow ale tu bardziej chodzi o kompresje i oczywiscie dalem przyklad tylko co do przetworzenia danych nie kompresji :)
dane obliczenia beda wykonywane po czesciach no ale jak juz wspomnialem chyba sobie z tym juz poradze wiec dzieki za pomoc. co jak co ale bym sie dalej oszukal funkcji ktorej nie ma :D
Avatar użytkownika
ch2_lbn
 
    Windows 7Firefox


  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Google [Bot] i 6 gości