Що таке streambuf? Як я ним користуюся?


80

Я намагаюся дізнатись трохи більше про те, як працюють потоки вводу-виводу в C ++, і я справді бентежусь, коли що використовувати.

Що саме таке streambuf?
Коли я використовую a streambuf, порівняно з a string, an istreamабо a vector? (Останні три я вже знаю, але не streambufпорівняю з ними, якщо вони взагалі знаходяться.)


Це погана абстракція буфера потоку.
Pubby

1
@Pubby: Е-е, що таке "буфер потоку"? Чим він відрізняється від потоку чи буфера?
user541686

3
@moshbear: Вибачте, я не уявляю, про що йдеться.
user541686

1
@Mehrdad Stroustrup's The C ++ Language Programming: Special Edition
moshbear

5
Якщо це допоможе вам почуватись краще, я працював із C ++ протягом 15 років і досі не отримую частину IO в бібліотеці C ++. Не було жодного проекту, де б я мав нагоду ним скористатися.
Неманья Трифунович

Відповіді:


50

Потокові буфери представляють пристрої введення або виведення та забезпечують інтерфейс низького рівня для неформатованого вводу-виводу цього пристрою. Потоки, з іншого боку, забезпечити більш високий рівень обгортки навколо буфера за допомогою основних функцій неформатований введення / виведення і особливо з допомогою відформатованих функцій введення / виводу (тобто, operator<<і operator>>перевантаження). Об’єкти потоку також можуть керувати життям буфера потоку.

Наприклад, файловий потік має внутрішній буфер потоку файлів. Потік управляє часом життя буфера, а буфер є тим, що забезпечує фактичні можливості читання та запису у файл. Оператори форматування потоку в кінцевому підсумку отримують доступ до неформатованих функцій вводу-виводу буфера потоку, тому вам доведеться лише використовувати функції вводу-виводу потоку, і вам не потрібно безпосередньо торкатися функцій вводу-виводу буфера.

Інший спосіб зрозуміти відмінності - поглянути на різні способи використання об’єктів мови. Потоки використовують грані, пов’язані з форматуванням, такими як numpunctі num_get. Ви також можете очікувати, що перевантаження потоку operator<<і operator>>для власних типів даних часу та грошей використовуватимуть грані форматування часу та грошей. Однак потокові буфери використовують фасети codecvt для перетворення між одиницями, які використовує їх інтерфейс, і байтами. Так, наприклад, інтерфейс для basic_streambuf<char16_t>використання char16_tі так basic_streambuf<char16_t>внутрішньо використовує codecvt<char16_t, char, mbstate_t>за замовчуванням для перетворення відформатованих char16_tодиниць, записаних у буфер, уcharодиниць, записаних на базовий пристрій. Отже, ви можете бачити, що потоки в основному призначені для форматування, а буфери потоків забезпечують інтерфейс низького рівня для неформатованого введення або виведення на пристрої, які можуть використовувати інше зовнішнє кодування.

Ви можете використовувати буфер потоку, коли вам потрібен лише неформатований доступ до пристрою вводу-виводу. Ви також можете використовувати буфери потоків, якщо хочете налаштувати кілька потоків, які мають спільний буфер потоків (хоча вам доведеться ретельно керувати часом життя буфера). Існують також спеціальні буфери потоку, які ви можете використовувати, наприклад, wbuffer_convertв C ++ 11, який виконує роль фасаду для, basic_streambuf<char>щоб зробити його схожим на широкий буфер потоку символів. Він використовує фасет codecvt, з яким він побудований, замість того, щоб використовувати фасет codecvt, прикріплений до будь-якої локалі. Зазвичай ви можете досягти того самого ефекту, просто використовуючи широкий буфер потоку, просякнутий мовою, що має відповідну грань.


14
Це запізнилося на 5 років, тому я не збираюся публікувати це як відповідь і не приймати цього, але для тих, хто все ще заплутаний термінологією, навіть прочитавши це: streambufце для необроблених даних (наприклад, необроблені байти, необроблені ints та ін.), тоді streamяк для приготовлених даних (текст, цілі числа, відформатовані як текст тощо). Іншими словами, streamпредставляє шар аналізу (або серіалізації). При роботі з простими рядками ви можете технічно використовувати будь-який, але значення інше: streambufозначає, що ви хочете, щоб вихідні дані були самим рядком, тоді як streamабстрагує кодування.
user541686

@Mehrdad Чи можу я запитати, що це означає, вимовляючи streamабстрактні фрагменти кодування ? : D Чи можете ви пояснити це трохи більше або надати додаткові матеріали?
Рік,

3
@Rick: Звичайно. streamвідповідає за читання та запис предметів на a streambuf. streambufвідповідає за збереження та відновлення байтів (або символів / слів / як би ви не хотіли їх називати) з місця зберігання байтів. Я мав на увазі відображення між об'єктами та байтами як "кодування". Прикладом цього є те, що a streamприймає, intа потім вирішує, як перетворити це на chars, і навпаки - він може використовувати формат big-endian, little-endian format, біт-зворотний формат, 7-bit- лише формат або щось інше. тобто він абстрагує формат зберігання.
user541686

69

За допомогою streambufми можемо працювати на ще нижчому рівні . Це дозволяє отримати доступ до базових буферів.

Ось декілька хороших прикладів: Скопіюйте, завантажте, переспрямуйте та трійник використовуйте streambufs C ++ і, посилаючись на порівняння, це може бути корисно

введіть тут опис зображення

Докладніше див. Тут: Бібліотека IOstream


2
Я всюди шукав щось, що могло б пояснити streambuf, а також цю статтю. Дякую, що допомогли мені його знайти!
wvdschel

1
Приклад - це завжди найкраще. Дякую
eigenfield
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.