LINUX.ORG.RU

Менять позицию и флушить или последовательно в StringBuilder и флушить?

 ,


0

1

Последовательно пишу несколько килобайт в файл через BufferedWriter, но изредка нужно возвращаться назад и перезаписывать несколько байт. Поэтому вместе с BufferedWriter разделяю SeekableByteChannel.

Когда хочу вернуться назад и переписать пару байтиков делаю сначала BufferedWriter#flush, а затем прыгаю на позицию SeekableByteChannel#position(long). И пишу несколько байтиков в BufferedWriter. Затем с такой же логикой возвращаюсь в текущий конец файла.

Глупо ли так делать? Может быстрее будет писать не сразу в файл, а в StringBuilder, а затем всё сбрасывать в файл последовательно?

★★★★★

Последнее исправление: foror (всего исправлений: 3)

Ответ на: комментарий от iZEN

Да мне сейчас не до этого, к тому же реальных данных пока нет, а на синтетике смысла нет. Тут весь вопрос как этот флaш в нативе работает, сразу на диск хреначит или в оперативке делает seek'и для килобайтных файлов...

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 1)

Сделай через MappedByteBuffer, совмести приятное с полезным. Тут тебе и stringbulder с append, и bufferedwriter средствами ОС

anonymous
()

Глупо ли так делать?

конечно. это имело бы смысл, ежель у тебя были бы большие файлы, пару кб писать надо в строку/байты, а потом это на диск спасать, просто и понятно.

vtVitus ★★★★★
()
Ответ на: комментарий от foror

У тебя кто-то отобрал исходники JDK что ли. flush пишет буферизованные данные в стрим, который обернут буферизованным, вот и всё. FileOutputStream просто вызывает функцию ОС write. Как это всё с SeekableByteChannel работает, предположить сложно, скорее всего на линуксе всё будет нормально. Но мешать старый I/O и новый I/O как-то некрасиво. С другой стороны как буферизовать SeekableByteChannel — непонятно. Я бы постарался обойтись только SeekableByteChannel и реализовать буферизацию вручную, обычно это несложно.

Глупо ли так делать? Может быстрее будет писать не сразу в файл, а в StringBuilder, а затем всё сбрасывать в файл последовательно?

Это в любом случае будет быстрей. Если память позволяет — так и делай.

Legioner ★★★★★
()

Пиши в буфер, сикай по нему, когда убедился что больше нечего изменять, отправляй буфер в файл и флаш его.

deep-purple ★★★★★
()
Ответ на: комментарий от Legioner

Но мешать старый I/O и новый I/O как-то некрасиво.

Files#newBufferedWriter фактически использует выше приведенные классы, я лишь оттуда выдрал в паблик SeekableByteChannel (чтобы сикать) - так что пусть они начнут с себя для начала...

Я щас убрал код с флашами и буферами, пишу и сикаю на StringBuilder'е через #append, #setLength и #setChartAt. Когда всё готово отправляю это дело (StringBuilder#getChars) напрямую в OutputStreamWriter#write без всяких буферов. Который пишет на #newOutputStream вытаскиваемый из FileSystemProvider, т.е. фактически это FileChannel.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 1)
Ответ на: комментарий от anonymous

Добавил это в TODO, когда будут реальные файлы и время потестю этот вариант.

foror ★★★★★
() автор топика
Ответ на: комментарий от foror

Files#newBufferedWriter фактически использует выше приведенные классы, я лишь оттуда выдрал в паблик SeekableByteChannel (чтобы сикать) - так что пусть они начнут с себя для начала...

Старое I/O это FileOutputStream. Сами стримы, конечно, использовать можно и нужно. Я думал, ты открываешь один файл в двух местах и одновременно редактируешь. Если ты там в приватных кишках ковыряешься, это уже совсем не комильфо, настоятельно не рекомендую так делать, как минимум ты уже забиваешься на конкретную JRE, возможно даже на её конкретную версию, причём без веских причин это делать.

Я щас убрал код с флашами и буферами, пишу и сикаю на StringBuilder'е через #append, #setLength и #setChartAt. Когда всё готово отправляю это дело (StringBuilder#getChars) напрямую в OutputStreamWriter#write без всяких буферов. Который пишет на #newOutputStream вытаскиваемый из FileSystemProvider, т.е. фактически это FileChannel.

Да, это нормальный вариант. Если стрингбилдеры размером в сотни миллионов символов создавать не будешь, проблем не будет.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

Если ты там в приватных кишках ковыряешься, это уже совсем не комильфо

К сожалению в джаве нету что-то типа godmode, как в расте блок unsafe, который бы позволял полный доступ на определенных участках кода. Поэтому мне пришлось делать copy-paste и создавать собственный класс с дублированнием кода из JDK. Ибо нужный мне объект был спрятан внутри метода в виде переменной, никаким рефлекшнем его оттуда не выдрать.

foror ★★★★★
() автор топика
Последнее исправление: foror (всего исправлений: 1)
Ответ на: комментарий от foror

MappedByteBuffer в жаве имеет одну неприятную особенность: его нельзя закрыть, когда тебе надо. Он закроется только когда отработает сборщик мусора. Поэтому, например, твоё приложение может продолжать использовать файл (и не давать отмонтировать ФС), хотя он тебе уже не нужен. Если это не проблема для тебя — можно использовать, штука удобная.

Legioner ★★★★★
()
Ответ на: комментарий от stevejobs

Не весь же? Всякую ручную аллокацию обещали оставить и перенести в другой ns, ибо хипстерская бигдата без нее не работает.

Deleted
()
Ответ на: комментарий от stevejobs

Ну в восьмерке же живет еще. Будет либа гвоздями прибит к восьмой Java.

Раз уж человеку хочется побыть богоподобным - пусть мучается.

TheKnight ★★★
()
Ответ на: комментарий от Deleted

Ты про VarHandles? Или про самый обычный Unsafe перенесенный в другой namespace?

TheKnight ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.