ストリームメソッド
ストリームメソッド
入力ストリームと出力ストリームは,ストレージメカニズムからバイトを読み書きするために要求されるストリーム操作を表すストリームメソッドを使って開かれる.ストリームメソッドを使うことで,ファイル,子プロセス,Webサーバ,バイトのインメモリリスト等のストレージメカニズムやデータソースから読み書きすることが可能になる.ストリームメソッドは圧縮や暗号化といったような変換も実行できる.たとえば,ユーザはストリームメソッドを使うことで圧縮されたファイルを開き,解凍されたコンテンツを読むことができる.ストリームへの操作では,物理メモリに適合しないような非常に大きいファイルへの操作も行える.
Wolframシステムは,ファイル,Webサーバ,文字列,外部コマンドからの読み書きのような一般的なニーズに応えられるストリームメソッドを提供している.また,に新しいストリームメソッドを加えることもできる.
読み書きのためにストリームを開いたら,Methodオプションを使って自分でストリームメソッドを指定することもできれば,Wolframシステムに,ストリーム名から自動的にストリームメソッドを選ばせることもできる.
Needs["CURLLink`"]
st = OpenRead["http://www.wolfram.com"]Find[st, "Mathematica"]Close[st]次はMethodオプションでストリームメソッドを選んで,Webサーバからストリームを開く:
Needs["CURLLink`"]
st = OpenRead["http://www.wolfram.com", Method -> "HTTP"]Find[st, "<body", IgnoreCase -> True]Close[st]Get["http://exampledata.wolfram.com/Collatz.m"]Collatz[5]st = OpenRead["http://exampledata.wolfram.com/Collatz.m"]ClearAll["Collatz`*"]Get[st]Collatz[4]Close[st]DefineInputStreamMethod["ByteList", {
"ConstructorFunction" ->
Function[{name, caller, opts}, If[MatchQ[opts, {___, "Bytes" -> {_Integer ...}, ___}],
{True, {0, "Bytes" /. opts}},
{False, $Failed}
]],
"ReadFunction" ->
Function[{state, n},
Module[{pos = state[[1]], bytes = state[[2]], bytesRead},
If[pos >= Length[bytes],
{{}, state},
bytesRead = Part[bytes, pos + 1 ;; Min[Length[bytes], pos + n]];
{bytesRead, {pos + Length[bytesRead], bytes}}
]
]],
"EndOfFileQFunction" -> ({#[[1]] >= Length[#[[2]]], #}&)
}]bytes = ToCharacterCode["Title: The Quick Brown Fox
Abstract: A fox jumps over dogs.
The quick brown fox jumped over the lazy dogs.
"];
st = OpenRead["Quick Brown Fox", Method -> {"ByteList", "Bytes" -> bytes}];
ReadList[st, String]//InputForm
Close[st];SetAttributes[rotateByte, Listable]
rotateByte[n_, x_] :=
With[{char = FromCharacterCode[x]},
Which[
UpperCaseQ[char], Mod[(x - 65) + n, 26] + 65,
LowerCaseQ[char], Mod[(x - 97) + n, 26] + 97,
True, x]
]
DefineInputStreamMethod["Rotate",
{
"ConstructorFunction" ->
Function[{streamname, caller, opts},
With[{state = Unique["RotateInputStream"]},
state["stream"] = OpenRead[streamname, BinaryFormat -> True];
state["positions"] = "Positions" /. Join[opts, {"Positions" -> 13}];
state["eof"] = False;
{True, state}
]],
"CloseFunction" -> Function[state, Close[state["stream"]]; ClearAll[state]],
"EndOfFileQFunction" -> Function[state, {state["eof"], state}],
"ReadFunction" ->
Function[{state, nBytes},
Module[{bytes = If[state["eof"], {}, BinaryReadList[state["stream"], "Byte", nBytes]]},
If[!ListQ[bytes], bytes = {}];
state["eof"] = Length[bytes] < nBytes;
{rotateByte[state["positions"], bytes], state}
]
]
}]Export["testrot13.txt", "guvf vf n jrnxyl-uvqqra cnffjbeq", "Text"]
FilePrint["testrot13.txt"]st = OpenRead["testrot13.txt", Method -> "Rotate"]ストリームメソッドがファイルの内容を変換するため,内容はReadが返すものとは異なっている:
Read[st, String]Close[st]
DeleteFile["testrot13.txt"]DefineOutputStreamMethod["Passthrough",
{
"ConstructorFunction" ->
Function[{streamname, isAppend, caller, opts},
With[{state = Unique["PassthroughOutputStream"]},
state["stream"] = OpenWrite[streamname, BinaryFormat -> True];
state["pos"] = 0;
{True, state}
]],
"CloseFunction" -> Function[state, Close[state["stream"]]; ClearAll[state]],
"StreamPositionFunction" -> Function[state, {state["pos"], state}],
"WriteFunction" ->
Function[{state, bytes},
Module[{result = BinaryWrite[state["stream"], bytes], nBytes},
nBytes = If[result === state["stream"], Length[bytes], 0];
Print["Wrote ", nBytes, " bytes"];
state["pos"] += nBytes;
{nBytes, state}
]
]
}
]st = OpenWrite["test.bin", Method -> "Passthrough", BinaryFormat -> True]BinaryWrite[st, Range[0, 255]]StreamPosition[st]Close[st]BinaryReadList["test.bin", "Byte"] === Range[0, 255]DeleteFile["test.bin"]