powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / буферизированное копирование
11 сообщений из 11, страница 1 из 1
буферизированное копирование
    #39048326
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такой примитивный код. Вся его задача -- сменить кодировку текстового файла. Проверку ошибок и using можно добавить, но они не критичны в рамках данной задачи.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
using System.IO;
using System.Text;

namespace Convert1251Utf8
{
    class Program
    {
        static void Main(string[] args)
        {
            string text = File.ReadAllText(args[0], Encoding.GetEncoding(1251));
            File.WriteAllText(args[1], text, Encoding.UTF8);
        }
    }
}



Вопрос. Как переделать этот код, чтобы копирование происходило буферизировано и работало бы на файлах особо большого объема > 2Gb. Порции по полгига, например. Желательно не порционировать по строкам, а просто прикрутить буфер на низком уровне потока чтения,записи файла.
...
Рейтинг: 0 / 0
буферизированное копирование
    #39048375
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin, самое простое читать и записывать построчно. Если ожидаются файлы с очень длинными строками, то читать и писать блоки символов:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
using (var srcStream = File.OpenRead(args[0]))
using (var srcReader = new BinaryReader(srcStream, Encoding.GetEncoding("windows-1251")))
using (var dstStream = File.OpenWrite(args[1]))
using (var dstWriter = new BinaryWriter(dstStream, Encoding.UFT8))
{
    char[] chars = new char[65000];
    for(;;)
    {
        int charsRead = srcReader.Read(chars, 0, chars.Length);
        if (charsRead == 0) break;
        dstWriter.Write(chars, 0, charsRead);
    }
}
...
Рейтинг: 0 / 0
буферизированное копирование
    #39048386
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazile,
Да спасибо, вот так наверное лучше записать.


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
            using (var srcStream = File.OpenRead(args[0]))
            using (var srcReader = new BinaryReader(srcStream, Encoding.GetEncoding("windows-1251")))
            using (var dstStream = File.OpenWrite(args[1]))
            using (var dstWriter = new BinaryWriter(dstStream, Encoding.UTF8))
            {
                const int BUFFER_SIZE = 50000000;
                var chars = new byte[BUFFER_SIZE];
                int charsRead;
                while ((charsRead = srcReader.Read(chars, 0, BUFFER_SIZE)) > 0)
                    dstWriter.Write(chars, 0, charsRead);
            }
...
Рейтинг: 0 / 0
буферизированное копирование
    #39048524
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin,

если доступен async/await (версия фреймворка позволяет), то ещё лучше будет асинхронный код. Можно взять здесь: Task-based Asynchronous Pattern , by Stephen Toub. В самом конце он во всех вариантах рассматривает вопрос.
И вообще архиполезная книга!
...
Рейтинг: 0 / 0
буферизированное копирование
    #39050727
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazile,

А всё-таки мы не правы. Команда OpenRead открывает потом с размером буфера по умолчанию. 4096



public static FileStream OpenRead(string path)
{
return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
}


public FileStream(string path, FileMode mode, FileAccess access, FileShare share)
: this(path, mode, access, share, 4096, FileOptions.None, Path.GetFileName(path), false)
{
}

А вопрос был про то, как чтение запись файла правильно буферизировать. Кто-то может сказать как правильно задавать размеры буфера.
...
Рейтинг: 0 / 0
буферизированное копирование
    #39050737
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin,

чего это за файлы такие текстовые по 2 гига
...
Рейтинг: 0 / 0
буферизированное копирование
    #39050750
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostta_voronin,

чего это за файлы такие текстовые по 2 гига

bcp output -- долгая история -- выгрузка в невиндовую файловую систему
...
Рейтинг: 0 / 0
буферизированное копирование
    #39050770
Фотография buser
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voroninА вопрос был про то, как чтение запись файла правильно буферизировать. Кто-то может сказать как правильно задавать размеры буфера.
Вот вы показали исподнее метода OpenRead - что после этого неясно? Вам непонятно что это за буфер? Или для чего вообще нужна буферизация? Или код ваш по прежнему валится с OutOfMemory?
...
Рейтинг: 0 / 0
буферизированное копирование
    #39050780
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voroninА всё-таки мы не правы. Команда OpenRead открывает потом с размером буфера по умолчанию. 4096
Какой ужас. Дальше ты откроешь что у Windows есть свой буфер чтения/записи и что у диска тоже есть кеш?

a_voroninА вопрос был про то, как чтение запись файла правильно буферизировать.
Интересно что неправильно в текущем решении? Оно возможно менее эффективно чем решение с большим размером буфера, но ничего неправильного я в нем не вижу.

a_voroninКто-то может сказать как правильно задавать размеры буфера.
Используй один из конструкторов FileStream принимающего bufferSize.
...
Рейтинг: 0 / 0
буферизированное копирование
    #39051135
Фотография a_voronin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
bazileИнтересно что неправильно в текущем решении? Оно возможно менее эффективно чем решение с большим размером буфера, но ничего неправильного я в нем не вижу.



Приведенный выше код нихрена, как выяснилось, не работает. Проверьте. Вот рабочий вариант

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
            var bufferSize = 5120000;
            using (var srcReader = new StreamReader(args[0], Encoding.GetEncoding("windows-1251"), false, bufferSize))
            using (var dstWriter = new StreamWriter(args[1], false, Encoding.UTF8, bufferSize))
            {
                string line;
                while ((line = srcReader.ReadLine()) != null)
                {
                    dstWriter.WriteLine(line);
                }
            }
...
Рейтинг: 0 / 0
буферизированное копирование
    #39051261
bazile
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
a_voronin, мой пример работает, твой нет потому что вместо типа char[], там используется byte[]. Это означает что байты записываются без перекодировки.

Есть правда одна ошибка - вместо File.Open(args[1])) лучше использовать File.Create(args[1])) чтобы если файл существует, он был бы открыт в режиме truncate.

Также использование BinaryWriter имеет еще один побочный эффект при использовании UTF8 - BOM не записывается. Однако для UTF8 все равно рекомендуется его не использовать и на чтении файла это не отразится при известной кодировке. Но если это проблема, то исправление очень простое.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / ADO.NET, LINQ, Entity Framework, NHibernate, DAL, ORM [игнор отключен] [закрыт для гостей] / буферизированное копирование
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]