Edytowanie/Modyfikacja pliku txt (lub innego)

Odpowiedz Nowy wątek
2014-12-13 14:19
0

Witam
Mam pytanie odnośnie modyfikacji pliku txt.
Mój plik txt jest w postaci ciągu kolejnych liczb typu long (8 bajtowych). Odczytanie np. 3 liczby jest proste bo InputStream ma metodę "skip", więc wykonanie na strumieniu "skip(16)" i potem rozpoczęcie czytania daje mi 3 liczbę typu long. Problem jest z tym jak zmodyfikować jakąś liczbę w środku (nie dopisywać do końca)? Czy można to zrobić bez przepisywania pliku? Czy analogicznie można też skasować wybrany fragment bajtów? ew. może to być inny format pliku niż txt.

Pozdrawiam

Pozostało 580 znaków

2014-12-13 14:26
0

Musisz pisać cały plik, a dokładniej to musisz zapisać od pozycji zmiany do końca.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell

Pozostało 580 znaków

2014-12-13 14:39
0

Ale czy na prawdę nie ma jakiegokolwiek sposobu? Czy w ogóle jest język, który coś takiego oferuje? Bo właśnie problem z tym, że te dane mogą być dosyć ogromne i przepisywanie wszystkiego mogłoby trwać dosyć długo.

Pozostało 580 znaków

2014-12-13 15:19
0

Może jakaś baza danych.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell

Pozostało 580 znaków

2014-12-13 15:39
0

Memory mapped file

Pozostało 580 znaków

2014-12-13 17:19
0

Zainteresuj się buforami i new i/o. Ta od wersji 7 daje takie możliwości aby zapisywać wycinek pliku tekstowego o wielkości jednego klastra, czyli w zależności od systemu i dysku 512 B lub 4 KB (ale trzeba napisać troszkę kodu, żeby mieć aż taką kontrolę). Obecnie obsługa plików w Javie jest tak niskopoziomowa jak to możliwe bo używane są mechanizmy direct access czyli w praktyce DMA. Robione jest to oczywiście przezroczysto poprzez nowe klasy obsługi plików i buforów i ich mapowanie przez jvm na api systemu. Wystarczy ogarnąć trochę standardowego javadoca.


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 1x, ostatnio: Olamagato, 2014-12-13 17:19

Pozostało 580 znaków

2014-12-14 12:50

@Olamagato zaciekawilo mnie co napisales o bezposrednim dostepie do urzadzen blokowych z Javy, bo nigdy o czyms takim nie slyszalem. Mozesz podac wiecej szczegolow?
@Parker mozesz slyszec rozne szalone sugestie, ale ja zaczalbym od rozwiazan przeznaczonych do takich zadan, czyli pliki mapowalne w pamieci (np. RandomAccessFile)

Pozostało 580 znaków

2014-12-14 17:42
0
wojciech.kudla napisał(a):

@Olamagato zaciekawilo mnie co napisales o bezposrednim dostepie do urzadzen blokowych z Javy, bo nigdy o czyms takim nie slyszalem. Mozesz podac wiecej szczegolow?

Oczywiście. Rzuć okiem na dokumentację klasy ByteBuffer i jej metody allocateDirect, a następnie na metody FileChannel.read i write. Alokowanie buforów wielkości bloków urządzenia lub jednostki alokacji plików pozwala na niskopoziomową obsługę zapisów i odczytów, a tym samym również na pełną kontrolę zapisywania i odczytywania poszczególnych sektorów dysku ponieważ plik jest alokowany zawsze od początku jakiegoś sektora dyskowego. Problem polega tylko na tym, że jeżeli kodowanie znaków nie daje odwzorowania 1:1 tak jak np. w UTF-8, to trzeba przed każdym zapisem używać metody Charset.encode(CharBuffer cb) dającej w wyniku zakodowany ByteBuffer (o innej długości niż CharBuffer dla UTF-8), a po odczycie Charset.decode(ByteBuffer bb) dający w wyniku odkodowany CharBuffer. Oczywiście kodowanie jest ze standardowego w pamięci JVM kodowania UTF-16LE (little endian) do wybranego, a dekodowanie odwrotnie, do UTF-16LE.
Dlatego, żeby to ogarnąć trzeba napisać trochę swojego kodu, który umożliwi wygodne zapisywanie i odczytywanie dowolnego kawałka tekstu do i z pliku.
[Aktualizacja]
Kodowanie i dekodowanie CharBuffera jest oczywiście obowiązkowe dla wszystkich rodzajów kodowań. Nie trzeba tego robić tylko w wypadku kodowania pliku tekstowego na UTF-16LE i odwrotnie. Można też kodować przed każdym zapisem jeden Charbuffer obejmujący cały tekst i wyjściowego ByteBuffera podzielić na mniejsze i każdy z nich zapisywać w razie potrzeby wcześniej używając metody FileChannel.position.


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 1x, ostatnio: Olamagato, 2014-12-14 18:05

Pozostało 580 znaków

2014-12-14 18:26
0

@Olamagato
Wydaje mi sie ze mylisz pojecia. ByteBuffer.allocateDirect() nie ma nic wspolnego z jakimkolwiek dostepem do dysku. Jedyna konsekwencja jego wywolania jest zaalokowanie bloku pamieci przy pomocy malloc. To samo w przypadku mmap, ktore jvm stosuje dla memory mapped files.
Kodowanie znakow nie ma tutaj nic do rzeczy.

Pliki mapowane na pamięć to po prostu uproszczenie, którego dzięki temu klient nie musi samodzielnie pisać często powtarzającego się kodu. Memory mapped file jest jednak dla celów odczytu i zapisu znaków niezbyt przydatne, choć w innych wypadkach jak najbardziej. - Olamagato 2014-12-14 22:37
Jeszcze co do alokowania obszaru pamięci, to menedżer pamięci JVM i tak korzysta przy żądaniu systemowym z malloc dla uzyskania pamięci dla sterty. Jest tak, bo JVM, to program de facto napisany w C/C++ (pomijając sporą część napisaną w Javie i skompilowaną do bytecode'u). Nie sprawdzałem tego, ale najprawdopodobniej pierwszy przydział równy jest wielkości minSize. Tak więc zarówno bufory ze sterty jak i bezpośrednie są realnie przydzielane przez malloca. Dlatego nie w tym rzecz czy to malloc czy nie. Rzecz w tym czy może na niej operować kontroler DMA. - Olamagato 2014-12-14 22:49
@Olamagato 1. Memory mapped file to nie jest zadne uproszczenie. To jest podstawowy i najbardziej wydajny mechanizm pracy z plikami w trybie swobodnego dostepu 2. Nie wiem czemu sie tak uparles na to DMA. I co to ma wspolnego z tym jak pracujesz z plikami w Javie. - wojciech.kudla 2014-12-15 09:21

Pozostało 580 znaków

2014-12-14 22:33
0

Pamięć jest alokowana przez mechanizmy systemu właśnie po to aby operacja dyskowa była przeprowadzana sprzętowo przez kontroler DMA, a nie programowo za pomocą procedury wykonywanej przez CPU. Jest to nic innego jak bezpośredni dostęp do dysku. Od JVM 7 żaden program Java napisany z użyciem nowego API nie może być mniej wydajny jeżeli chodzi o operacje dyskowe od kodu natywnego takiego jak napisany w C/C++. Natomiast kodowanie znaków nie ma z tym nic wspólnego, to oczywiste.
[Aktualizacja]
Oczywiście bufory alokowane bezpośrednio nie muszą wcale być wielkościami sektorów czy jednostek alokacji plików. API systemu też tego nie wymaga. Różnica między alokowaniem bezpośrednim, a nie bezpośrednim jest tylko taka, że pomijany jest krok przepisywania przez kod systemu (czyli CPU) bufora na stercie JVM do prywatnego obszaru systemowego na który jest zaprogramowany kontroler DMA w taki sposób, że po przeprogramowaniu kontroler ten operuje bezpośrednio na pamięci RAM dostępnej dla kodu Javy/JVM (bez znaczenia czy w danym momencie skompilowanego w locie do kodu maszynowego czy kodu maszynowego JVM interpretującego bytecode). Oczywiście przeprogramowanie jest standardową procedurą dostępną dla natywnego kodu maszynowego, natomiast Java we wcześniejszych wersjach pracowała podobnie jak procedury DOS/BIOS zawierające krok przepisywania danych przez CPU. Jest to niewydajne. Szczególnie dla dużych ilości danych na jakich operuje się obecnie.


Jeżeli ktoś komuś coś, ewentualnie nikt nikomu nic, to właściwie po co...?
edytowany 1x, ostatnio: Olamagato, 2014-12-14 23:03

Pozostało 580 znaków

2014-12-15 09:34
0

Pamięć jest alokowana przez mechanizmy systemu właśnie po to aby operacja dyskowa była przeprowadzana sprzętowo przez kontroler DMA, a nie programowo za pomocą procedury wykonywanej przez CPU. Jest to nic innego jak bezpośredni dostęp do dysku.

Dobrze byloby gdybys poznal roznice pomiedzy malloc a mmap, bo ewidentnie mylisz pojecia.

Od JVM 7 żaden program Java napisany z użyciem nowego API nie może być mniej wydajny jeżeli chodzi o operacje dyskowe od kodu natywnego takiego jak napisany w C/C++.

A mozesz opisac w jaki sposob Java realizuje te gwarancje? Ja np. do tej pory wiele funckjonalnosci osiagam przez wywolania jni, bo Java nie oferuje wielu optymalizacji. Zabawki takie jak lock xadd albo cmov dla inkrementacji atomicow pojawily sie dopiero w Java 8.

[Aktualizacja]
Oczywiście bufory alokowane bezpośrednio nie muszą wcale być wielkościami sektorów czy jednostek alokacji plików. API systemu też tego nie wymaga. Różnica między alokowaniem bezpośrednim, a nie bezpośrednim jest tylko taka, że pomijany jest krok przepisywania przez kod systemu (czyli CPU) bufora na stercie JVM do prywatnego obszaru systemowego na który jest zaprogramowany kontroler DMA w taki sposób, że po przeprogramowaniu kontroler ten operuje bezpośrednio na pamięci RAM dostępnej dla kodu Javy/JVM (bez znaczenia czy w danym momencie skompilowanego w locie do kodu maszynowego czy kodu maszynowego JVM interpretującego bytecode). Oczywiście przeprogramowanie jest standardową procedurą dostępną dla natywnego kodu maszynowego, natomiast Java we wcześniejszych wersjach pracowała podobnie jak procedury DOS/BIOS zawierające krok przepisywania danych przez CPU. Jest to niewydajne. Szczególnie dla dużych ilości danych na jakich operuje się obecnie.

  1. Bufory na stercie sa niemapowalne na pliki. Nie wiem skad pozyskales wiedze ze sa.
  2. Do skorzystania z DMA nie jest potrzebne zadne "przeprogramowanie". To juz jakas kompletna bzdura.
  3. Zero-copy data transfer jest w Javie dostepny od 1.5 poprzez NIO (zwlaszcza bufory i channele).

Twoje posty brzmia jakbys wiedzial o czym mowisz, ale ewidentnie miesza ci sie kilka tematow jednoczesnie. Pomysl o tym w ten sposob: ktos poczatkujacy przeczyta sobie takiego posta i bedzie mial bledne przekonanie o tym jak rzeczy w Javie dzialaja.
Z checia podesle liste dobrych lektur na poczatek, ktore pomoglyby ci uporzadkowac wiedze, ktora juz masz.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0