Страницы

Поиск по вопросам

Показаны сообщения с ярлыком filestream. Показать все сообщения
Показаны сообщения с ярлыком filestream. Показать все сообщения

четверг, 9 апреля 2020 г.

Прочитать с середины файл без чтения его начала на Rust'е

#файлы #потоки_данных #filestream #rust #fstream

                    
let f = File::open("file").unwrap();
let reader = BufReader::new(f).seek(io::SeekFrom::Start(2));
for b in reader.iter().next() {
    println!("{}", b);
}


Выводит то, что находится внутри io::SeekFrom::Start, т.е. 2.
    


Ответы

Ответ 1



Какой-то странный цикл у вас. По идее должно быть как-то так: let f = File::open("file").unwrap(); let mut reader = BufReader::new(f); reader.seek(io::SeekFrom::Start(2)).unwrap(); for b in reader.bytes() { println!("{}", b); } Метод seek() возвращает Result, то есть новую позицию в файле. Он вызывается на &mut self, значит reader должен быть mut, иначе не заработает. Что делает ваш код: вы открываете файл и смещаете указатель на 2 байта, сохраняя Result в reader. Потом вы преобразовываете Result в итератор с помощью iter() и вызываете на итераторе next(), получаете Option, равный Some(2). А потом по опции итерируете (Option<_> реализует IntoIterator, так что этому типу можно итерировать). Итератор весело выдаёт один элемент — 2. Чтобы избежать подобных ошибок в будущем, внимательно читайте документацию на используемые трейты и типы: ни в трейте Read, ни в типе BufReader нет метода iter(), однако в Read есть метод bytes(), который вам был нужен. А вот метод Seek::seek возвращает Result. Кроме того стоит больше прочитать про интерфейс итераторов, так как вы, судя по всему, до конца не поняли эту идею, раз вызываете на итераторе метод next() явно.

воскресенье, 15 марта 2020 г.

Не срабатывает fputs

#cpp #c #файлы #filestream


#include 
using namespace std;
int main()
{
    char tmpstr[255];
    FILE *stream;

    stream = fopen("ase.txt", "r+");

    fgets (tmpstr, 255, stream);
/*  fseek(stream, 0, SEEK_CUR);     */
    fputs("spice", stream);             // fprintf(stream, "%s","spice");  

    fclose(stream);
    return 0;
}


Почему-то не происходит запись в файл, однако, если раскомментировать строчку fseek
- запись происходит. Аналогичная ситуация, если использовать fprintf вместо fputs.
Почему так происходит?
    


Ответы

Ответ 1



Согласно стандарту С (7.21.5.3 The fopen function) 7 When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters endof-file. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations. Таким образом, вы не можете выполнять операцию записи в файл сразу же после операции чтения файла без промежуточного вызова одной из функций: fflush, fseek, fsetpos, или rewind

воскресенье, 8 марта 2020 г.

Как распарсить Stream

#c_sharp #потоки_данных #filestream


Можно ли распарсить поток? То есть получить из него имя файла, путь к файлу, ну и
то что лежит в файле(в виде текста конечно)?
    


Ответы

Ответ 1



В общем случае такой информации в потоках нет. Эти сущности предоставляют собственно уже содержимое ресурса (например, файла) и некоторые базовые свойства (например, размер, см. свойство Length -- однако не все потоки это поддерживают), а также возможность навигации и чтения. Так что все, что вы можете вытянуть из стрима -- собственно его содержимое. Если же у вас есть именно FileStream, то полный путь к файлу, включая имя, можно взять из свойства Name. Содержимое удобнее всего прочитать через StreamReader: using (FileStream stream = ...) using (var reader = new StreamReader(stream)) { string content = reader.ReadToEnd(); }

пятница, 24 января 2020 г.

NodeJS Как записать в Buffer полученные данные из busboy?

#javascript #nodejs #файлы #fileupload #filestream


Добрый вечер. 

Использую для получения данных(картинки) busboy. 

Получаю данные так: 

var buffer = Buffer.allocUnsafe(filesize);
req.recvSize = 0;  
 file.on('data', function (data) {
            buffer.write(data,req.recvSize,data.length);
            req.recvSize += data.length;
 });


На выходе такая вот ошибка: 

buffer.js:761
return this.utf8Write(string, offset, length);
^

TypeError: Argument must be a string
at TypeError (native)
at Buffer.write (buffer.js:761:21)


Вариант с concat мне не подходит, так как я изначально знаю размер файла и далее
мне не нужны лишние действия(из-за этого и решил сразу писать в буффер). 

copy тоже не особо хочется использовать, так как все же write записывает данные на
прямую, без лишнего копирования(если вы готовы оспорить это, то буду рад почитать ваше
мнение в комментариях)

Как можно решить такую ошибку или как правильнее будет принимать данные?
    


Ответы

Ответ 1



Не очень понятно по куску кода, что такое file. Скорее всего это ваш request к серверу. Проверьте, не указали ли вы где-то кодировку. Что-то типа res.setEncoding('utf8') В этом случае как раз на событие data у вас придёт объект типа строка, а не Buffer. Но в целом, вы особо не выигрываете, относительно concat массива буферов Buffer.concat(buffers). Потому что в data событие вам уже приходит готовый выделенный объект Buffer, и разницы, когда его копировать - изначально, или в самом конце не очень много. К тому же, несмотря на заявленную длину файла вам фактически может и не приехать столько данных (порвётся соединение, сервер передумает), а вы уже выделили память подо всё это. Кстати, внутри Buffer.concat использует copy, для копирования данных, а не write

четверг, 19 декабря 2019 г.

Можно ли связать файловый поток с потоком cout?

#cpp #cpp11 #filestream


Я рассчитывал на то, что cout будет выводить всё, что было записано в файловый поток,
но этого не происходит.

using namespace std;

int main(int argc, char *argv[])
{
    fstream out("hello_world.txt",ofstream::out, ofstream::trunc);
    out.tie(&cout);
    out << "Hello World!" << endl;
    out.close();

    return 0;
}

    


Ответы

Ответ 1



std::basic_ios::tie это не про это и то, чего Вы хотите добиться реализуется не так просто. Точнее, для этого нет встроенных средств, которые можно использовать не добавляя кода. То, что Вы хотите можно реализовать следующий образом: делаем свой буфер, который можно связывать с несколькими буферами, потом свой поток данных, который будет использовать этой буфер. Выглядеть это может так: class Multibuffer: public std::streambuf { public: void tieBuffer(std::streambuf* buffer) { m_Buffers.emplace_back(buffer); } int overflow(int character) override { for(auto& buffer : m_Buffers) buffer->sputc(character); return character; } private: std::vector m_Buffers; }; class Multistream: public std::ostream { public: Multistream(): std::ostream(nullptr) { rdbuf(&m_Buffer); } void tie(std::ostream& stream) { stream.tie(this); m_Buffer.tieBuffer(stream.rdbuf()); } private: Multibuffer m_Buffer; }; И использовать это можно так: Multistream multi; multi.tie(out); multi.tie(std::cout); multi << "Hello World!" << endl; out.close(); Только учтите, что это слишком базовая реализация буфера, в которой нет проверок на eof и прочих. Но его можно доработать под Ваши нужды.

Ответ 2



Лучше так не делать. Нужно STDOUT перенаправить в файл, запусти программу как program_name > hello_world.txt Но если очень нужно, например для демона, то: открой файл при помощи ::open() - не стоит использовать ::fopen(), так как появится головная боль с буферами и их соглосованием. сделай дупликацию дескрипторов при помощи dup2() ... PROFIT! если точнее, то просто продолжаешь пользовать std::cout как и раньше, но текст будет попадать в файл. Закрывать уже нужно будет сам файловый дескриптор. Вот пример: #include #include #include #include #include using namespace std; int main() { auto fd = ::open("./hello.txt", O_APPEND | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); // Дуплицируем наш дескриптор на стандартный выход dup2(fd, STDOUT_FILENO); // С этого момента, всё, что попадает в std::cout - попадает в файл. cout << "Hello, world!\n"; cout << flush; ::close(fd); return 0; } Аналогично можно сделать для STDERR_FILENO - стандартный поток ошибок. Он используется std::cerr и std::clog (первый не буфферизированный, второй, как и std::cout - буфферизированный). Для Windows стоит уточнить поведение и где находятся объявления ::open() и dup2() и их альтернативы: dup/dup2 vs _dup/_dup2 open vs _open vs _sopen

пятница, 28 июня 2019 г.

Прочитать с середины файл без чтения его начала на Rust'е

let f = File::open("file").unwrap(); let reader = BufReader::new(f).seek(io::SeekFrom::Start(2)); for b in reader.iter().next() { println!("{}", b); }
Выводит то, что находится внутри io::SeekFrom::Start, т.е. 2.


Ответ

Какой-то странный цикл у вас. По идее должно быть как-то так:
let f = File::open("file").unwrap(); let mut reader = BufReader::new(f); reader.seek(io::SeekFrom::Start(2)).unwrap(); for b in reader.bytes() { println!("{}", b); }
Метод seek() возвращает Result, то есть новую позицию в файле. Он вызывается на &mut self, значит reader должен быть mut, иначе не заработает.
Что делает ваш код: вы открываете файл и смещаете указатель на 2 байта, сохраняя Result в reader. Потом вы преобразовываете Result в итератор с помощью iter() и вызываете на итераторе next(), получаете Option, равный Some(2). А потом по опции итерируете (Option<_> реализует IntoIterator, так что этому типу можно итерировать). Итератор весело выдаёт один элемент — 2.
Чтобы избежать подобных ошибок в будущем, внимательно читайте документацию на используемые трейты и типы: ни в трейте Read, ни в типе BufReader нет метода iter(), однако в Read есть метод bytes(), который вам был нужен. А вот метод Seek::seek возвращает Result. Кроме того стоит больше прочитать про интерфейс итераторов, так как вы, судя по всему, до конца не поняли эту идею, раз вызываете на итераторе метод next() явно.

среда, 5 июня 2019 г.

Не срабатывает fputs

#include using namespace std; int main() { char tmpstr[255]; FILE *stream;
stream = fopen("ase.txt", "r+");
fgets (tmpstr, 255, stream); /* fseek(stream, 0, SEEK_CUR); */ fputs("spice", stream); // fprintf(stream, "%s","spice");
fclose(stream); return 0; }
Почему-то не происходит запись в файл, однако, если раскомментировать строчку fseek - запись происходит. Аналогичная ситуация, если использовать fprintf вместо fputs. Почему так происходит?


Ответ

Согласно стандарту С (7.21.5.3 The fopen function)
7 When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters endof-file. Opening (or creating) a text file with update mode may instead open (or create) a binary stream in some implementations.
Таким образом, вы не можете выполнять операцию записи в файл сразу же после операции чтения файла без промежуточного вызова одной из функций: fflush, fseek, fsetpos, или rewind