2010-06-01 4 views
5

Я использую Java DataInputStream с scala для анализа простого двоичного файла (что очень плохое из-за отсутствия неподписанных типов даже в scala, но это совсем другая история) ,Функциональный подход к программированию для потоков ввода/вывода Java

Однако я нахожу себя вынужденным использовать изменяемую структуру данных, поскольку потоки Java по сути являются сохраняющими состояние объектами.

Что такое хороший дизайн для переноса потоков Java с хорошей функциональной структурой данных?

ответ

5

В настоящее время идет проект, целью которого является создание IO API для Scala: scala IO Он вдохновлен Java 7 NIO API. Это все еще WIP, но из него вы можете получить некоторые интересные идеи. Там также есть несколько примеров того, как их использовать, которые можно найти: here

+0

Не является ли основной момент NIO асинхронным? Я не уверен, что хочу асинхронный поиск данных. Это может сделать простые вещи более сложными. –

+0

@ Elazar 'java.nio' - это не только асинхронный ввод-вывод, но и множество функциональных возможностей для« обычных »синхронных операций. Тот факт, что scala-io построен на 'java.nio', не обязательно означает, что он предназначен только для асинхронного ввода-вывода. – Jesper

1

Посмотрите на IO Monad от Haskell за чистый функциональный подход.

Прагматичная реализация Scala реализует Iterator/Iterable на основе Stream. Например, scala.io.Source supports.

+0

Прагматическая реализация Scala не подходит, скажем, для двоичного потока. Что, если я хочу прочитать int, а затем короткий? Итератор не сможет справиться с этим.И даже если бы я мог сохранить состояние, используя его! –

+0

Каждая реализация должна определить тип M [T] как контейнер вашего потока. Поэтому T должен поддерживать T.toShort и T.toInt для чтения текущего значения. В противном случае M [_] будет неоднородным контейнером. –

2

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

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

Большинство функциональных структур данных позволяют абстрагироваться от числа копий. Например, список позволяет вам выполнять операции над отдельным элементом ко всем элементам удобными способами (map, reduce и т. Д.). Но когда вы хотите прочитать файл, вам нужно абстрагироваться от типа данных, и, кроме того, вы фактически не хотите, чтобы он был полностью абстрактным - вы хотите сопоставить какой-то шаблон, который вы ожидаете. Как вы указываете этот шаблон - и что делать с условиями ошибки - я подозреваю, ядро ​​вашей задачи чтения двоичных файлов.

(Обратите внимание, что если вы работаете на одном из этих многоядерных ящиков Sun (например, T2000), вам не требуется неизменность для безопасности, поскольку один поток достаточно быстр, чтобы обрабатывать все низкоуровневые обработка ввода.)

Одна из возможностей - рассматривать чтение двоичного файла как проблему синтаксического анализа. На данный момент у Scala нет надежной библиотеки, но см. this thread за хороший код, написанный Полом Филлипсом, который помогает в этом отношении.

Другая возможность заключается в том, чтобы создать какой-то шаблон самостоятельно, как

List(classOf[Float],classOf[Int],classOf[String]) 

, а затем написать что-то, что разбирает этот поток последовательно с заявлениями матча:

val FloatClass = classOf[Float] 
listEntry match { 
    case FloatClass => // Read float 
    ... 
} 

Такого рода вещи делают работу чтения двоичных файлов намного проще, и это, по крайней мере, сорт, так как вы можете отобразить свой входной поток байтов в List[Any], а затем использовать сопоставление образцов для захвата o ut данные, которые вы хотите.

Смежные вопросы