バイナリファイルの追記 – プログラミング – Home

バイナリファイルの追記
 
通知
すべてクリア

[解決済] バイナリファイルの追記


ホホーム
 ホホーム
(@ホホーム)
ゲスト
結合: 18年前
投稿: 4
Topic starter  

バイナリの追加方法がわかりません。
OpenMode.AppendにしてもFilePutでモードがおかしいとエラーになります。
Seekを使って最後にしようと思っても最後のバイト位置がわかりません。
バイナリの追記方法を教えてください。
.net2005を使ってます。

FileOpen(1, Test.bin, OpenMode.Binary)
Seek(1, ???)
FilePut(1, data)'データを追記
FileClose(1)


引用未解決
トピックタグ
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

FileLenでファイルの長さがわかるから、それをSeekの引数にすればいいかも…
でも、この関数群はVB6.0との互換用ですから、FileStreamなりMy.FileSystemなり
使った方がいいかと思われます。


返信引用
ホホーム
 ホホーム
(@ホホーム)
ゲスト
結合: 18年前
投稿: 4
Topic starter  

色々やってみましたがわかりません

Public Structure Data
Public data1 As Integer
Public data2 As Integer
Public data3 As Integer
End Structure

data.data1 = 0
data.data2 = 1
data.data3 = 2
My.Computer.FileSystem.WriteAllBytes _
(Test.bin, data, True)

これで書き込もうとしましたが
dataのところでエラーがでます。
dataをbyteの1次元配列にしないといけないようです。

このあたりがよくわからず断念。

次にBinaryWriterを使ってみましたが

Dim binWriter As New BinaryWriter( _
File.Open(test.bin, FileMode.Create))
Try
  data.data1 = 0
  data.data2 = 1
  data.data3 = 2
binWriter.Write(data)
Finally
binWriter.Close()
End Try

dataのところでエラーがでます。
引数がオーバーロードが存在しないと言われました。
結局構造体では書込めないようです。

構造体を書き込む場合の手法とかどうやるんでしょうか?


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

構造体の場合、バイト型配列にしてから書き込む必要がありそうです。

Marshal.StructureToPtr メソッドを使って、IntPtr型に変換し
Marshal.Copy メソッドを使って、Byte型配列を取得するとか。
(Marshal.SizeOfで構造体のサイズを取得できる)

また、BinaryFormatterってなのもあるようです。(普通はこちらを使いそう)


返信引用
ホホーム
 ホホーム
(@ホホーム)
ゲスト
結合: 18年前
投稿: 4
Topic starter  

やってみましたがうまく出来ません
Writeする直前のbyDataの中身が全て0になってます。
どこかおかしいところはありますか?

Dim data As Data
Dim byData(Marshal.SizeOf(data)) As Byte

Dim binWriter As New BinaryWriter( _
File.Open(test.bin, FileMode.Append))
Dim size As Integer = Marshal.SizeOf(data)
Dim ptr As IntPtr = Marshal.AllocHGlobal(size)
Try
data.data1 = 1
data.data2 = 2
data.data3 = 3
Marshal.StructureToPtr(data, ptr, True)
Marshal.Copy(byData, 0, ptr, size)
binWriter.Write(byData)
Finally
binWriter.Close()
End Try
Marshal.FreeHGlobal(ptr)


返信引用
aetos
(@aetos)
Noble Member
結合: 5年前
投稿: 1480
 

そもそも、C でやっていたように、ファイルに構造体をそっくり書き込む/ファイルか
ら構造体にごっそり読み込むというのは、.NET ではできない…ことはないけれど、標準
的な方法で無いということを、ずいぶん前に知りました。
構造体をファイルに書き込みたい場合、その構造体に ISerializable を実装させて、構
造体自身に行わせるのがよい気がします。
ISerializable 実装の中では、BinaryReader / BinaryWriter を使うのがよいでしょ
う。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

> Marshal.Copy(byData, 0, ptr, size)
引数の指定が間違っています。
http://msdn2.microsoft.com/ja-jp/library/ms146631(VS.80).aspx
より
<MSDN>
Public Shared Sub Copy ( _
source As IntPtr, _
destination As Byte(), _
startIndex As Integer, _
length As Integer _
)
</MSDN>

一応試しに作ってみた。

Imports System
Imports System.IO
Imports System.Runtime.InteropServices

<StructLayout(LayoutKind.Sequential)> _
Public Structure Data
Public data1 As Integer
Public data2 As Integer
Public data3 As Integer
End Structure

Public Module Sample
Public Sub Main(ByVal args() As String)
Dim d As New Data
Dim binWriter As BinaryWriter

Try
d.data1 = 0
d.data2 = 1
d.data3 = 2
binWriter = New BinaryWriter( _
File.Open(test.bin, FileMode.Append))
binWriter.Write(StructureToBytes(d))
Finally
binWriter.Close()
End Try

End Sub

Private Function StructureToBytes(ByVal struct As Object) As Byte()
' 構造体のサイズ
Dim struct_size As Integer = Marshal.SizeOf(struct)
' アンマネージメモリの確保
Dim ptr As IntPtr = Marshal.AllocHGlobal(struct_size)
' 戻り値用の配列の作成
Dim bin As Byte() = New Byte(struct_size){}

' アンマネージメモリにマーシャリング
Marshal.StructureToPtr(struct, ptr, struct_size)
' アンマネージメモリから配列にコピー
Marshal.Copy(ptr, bin, 0, struct_size)

' アンマネージメモリの解放
Marshal.FreeHGlobal(ptr)

Return bin
End Function
End Module


返信引用
ホホーム
 ホホーム
(@ホホーム)
ゲスト
結合: 18年前
投稿: 4
Topic starter  

サンプルありがとうございます。
おかげさまで書込みが出来ました。

>>Dim bin As Byte() = New Byte(struct_size){}
この部分は1バイト余分にかかれてたので
Dim bin As Byte() = New Byte(struct_size-1){}
と、修正しました。
なぜか指定数+1できているようです。
なぜこんな仕様なのか…

とにかく解決いたしました。
レスくれた皆さんありがとうございました。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

>なぜか指定数+1できているようです。
VBの配列は 0~n で、要素数が n+1 であることを失念していました。
(C#やC++では 0~n-1 で、要素数が n)

ですので、
>Dim bin As Byte() = New Byte(struct_size-1){}
となるんですね。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました