String型をByte型にしたい

タグの編集
投稿者 O-157  (その他) 投稿日時 2011/3/9 10:34:37
TextBoxなどに入力したByte型の文字列をエンコードせずにByte型に変換したいのですが、どうしたら良いのでしょうか?100104106102106104106104130136130138130135130136130134130138130136130136104104104106104103104104103130136130135104103107104130135130134103104106107106107108106115971301451301361301821302251301641301611171051191041301381301511301361301511061191111301621301681301511301361301511301381301381301361301511301351301471301501301361151041301351301511301381301391301401031031171171061051011061001061041111191302171302351301661041031311479813114710414313810611913018213016513024113013013013013013513021413018213022513013813019313018213022513014513013813016413016113016613013813013513021113014613013613013813013513013613013813013613013013024113015013013613015213014112966130138130165130164130161130168
がByteにしたいStringです。よろしくお願いします。 
 
  
投稿者 YuO  (社会人) 投稿日時 2011/3/9 11:30:40
Byte型の文字列,というのは存在しないのですが……。

その文字列をどのように見てByte型にしたいのですか。
文字列をByte列に変換する方法は一意ではないため,どの方法を使うかを決定しないと変換できません。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/3/9 11:31:15
Byte型というか、Byte配列ですよね。

> エンコードせずにByte型に変換したいのですが
どういう意味でしょうか?

> がByteにしたいStringです。
その String をどのようなバイナリにしたいのかを
書いてもらわないと、意味が無いと思いますよ。

単純に "0010" という文字列の場合で考えても、
その変換にはいろいろな解釈がありえるわけで。

 &H0A                … 単一の10進数として扱う。(256以上の値は変換エラー)
 &H00,&H0A           … 2桁の10進数が2つ並んだものとして扱う。
 &H00,&H00,&H01,&H00 … 1桁の10進数が4つ並んだものとして扱う。
 &H00,&H10           … 4桁の16進数として扱い、ビッグエンディアンで配置。
 &H10,&H00           … 4桁の16進数として扱い、リトルエンディアンで配置。
 &H30,&H30,&H31,&H30 … 数字 4 文字とみなして、それを ASCII なバイナリとする。
投稿者 とくま  (社会人) 投稿日時 2011/3/9 11:31:21
>エンコードせずに
一定の規則に従ってデータに置き換える行為自体を差すので
使い方を間違っているような気もします。

1文字ずつ切り取って文字列→数値変換し、掛け算と足し算で
0~255 の値にするだけではないでしょうか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/3/9 11:56:42
変換ルールだけでなく、開発環境も明示してください。
VB のバージョンによってコードが変わってくるでしょうから。

とりあえず、現行バージョンの VB と仮定して…。

10進数として1文字ずつ変換。"12" → &H1, &H2
Dim bin() As Byte = Array.ConvertAll(Of CharByte)(TextBox1.Text, AddressOf Convert.ToByte)


10進数として2文字ずつ変換。"1061" → &H0A, &H3D
Private Function ToBinary(ByVal s As StringAs Byte()
    Dim b As New List(Of Byte)()
    For I As Integer = 1 To Len(s) Step 2
        b.Add(CByte(Mid(s, I, 2)))
    Next
    Return b.ToArray()
End Function


16進数として2文字ずつ変換。"1061" → &H10, &H61
Private Function ToBinary(ByVal s As StringAs Byte()
    Dim b As New List(Of Byte)()
    For I As Integer = 1 To Len(s) Step 2
        b.Add(Convert.ToByte(Mid(s, I, 2), 16))
    Next
    Return b.ToArray()
End Function
投稿者 O-157  (社会人) 投稿日時 2011/3/9 12:03:00
すいません、説明不足でしたね…
My.Computer.FileSystem.ReadAllBytesで読み取ったByteを結合してStringにした後、TextBoxなどで編集してMy.Computer.FileSystem.WriteAllBytesで書き込みたいのですが、ByteにそのままStringが入れられずに困っています。
投稿者 YuO  (社会人) 投稿日時 2011/3/9 12:10:42
> My.Computer.FileSystem.ReadAllBytesで読み取ったByteを結合してStringにした後
これは具体的に何をしているのですか。
ここで何らかの操作をしているのですよね。
当然,逆変換をしないとStringからByte列に戻すことはできません。
投稿者 O-157  (社会人) 投稿日時 2011/3/9 12:44:50
>ここで何らかの操作をしているのですよね。
        For dd As Integer = 0 To dj.Length - 1
            by += CStr(dj(dd))
        Next
という文を使い、ByteからStringにしたのですが、逆が出来ないのです…
投稿者 shu  (社会人) 投稿日時 2011/3/9 13:19:27
> という文を使い、ByteからStringにしたのですが、逆が出来ないのです… 
魔界の仮面弁士さんが言っているように文字列をどこで区切ってどのように
byteにするのか決まってないと無理かと思います。

> by += CStr(dj(dd))
元の変換をこのように行っていると出来た文字列は1から3桁の可変になり区切りがないので
元に戻すのは無理だと思います。
投稿者 るきお  (社会人) 投稿日時 2011/3/9 13:20:23
文字列とバイト型の配列の変換には、EncodingクラスのGetStringメソッドとGetBytesメソッドを使います。
(その他の方法もありますが、これが一番簡単と思います。)

ご存知と思いますが、文字列を文字コード(≒バイト型)にするときには
どの文字にどの文字コードを割り当てるかを必ず決めておかなければならないので、
エンコードしないでバイト型の配列にするというのは意味がわからない言葉になってしまいます。
(バイト型の配列にする ≒ エンコードするということです。)

My.Computer.FileSystem.ReadAllBytesで読み込んで、
文字列を編集後My.Computer.FileSystem.WriteAllBytesで書き込む例を作りましたので、
参考にしてください。

※本当はByteの配列を結合したいとのことですので、本来やりたいこととちょっと違うと思いますが、
ノウハウはくみ取っていただけるかと思います。

Dim fileName As String = "C:\vb\test.txt"

'shift-jisの場合 
Dim encode As System.Text.Encoding = System.Text.Encoding.GetEncoding("shift_jis")

'utf-8の場合 
'Dim encode As System.Text.Encoding = System.Text.Encoding.UTF8 

Dim readBytes As Byte()
readBytes = My.Computer.FileSystem.ReadAllBytes(fileName)

Dim text As String
text = encode.GetString(readBytes)

text &= "あああああ" & vbNewLine & "いいいいい"

Dim writeBytes As Byte()
writeBytes = encode.GetBytes(text)

My.Computer.FileSystem.WriteAllBytes(fileName, writeBytes, False)
投稿者 shu  (社会人) 投稿日時 2011/3/9 13:48:38

元のbyte配列 {1,11,111,1,11} => "111111111"
元のbyte配列 {11,1,11,11,1,1} => "111111111"
同じになります。
"111111111"をどっちの配列(または他のパターン)にするのか分かりません。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/3/9 14:15:35
> by += CStr(dj(dd))
せめて
 by &= dj(dd).ToString("000")
のように 3 桁固定であるとか、あるいは
 by &= ("," & CStr(dj(dd)))
のように、区切り文字付きであれば復元できたのですけれどね。

既に指摘されているように、現状の変換規則では原理的に復元不可能ですが、
他の変換規則でも良いなら。

《案1》"56-78-9A-BC" 形式の16進数文字列
'バイナリ→文字列変換 
Dim bin() As Byte = System.IO.File.ReadAllBytes("C:\WINDOWS\system32\calc.exe")
Dim hexText As String = BitConverter.ToString(bin)
'文字列→バイナリ復元 
Dim bin2() As Byte = Array.ConvertAll(Split(hexText, "-"), Function(s) Convert.ToByte(s, 16))


《案2》BASE64変換(64種類の英数字で表現)
'バイナリ→文字列変換 
Dim bin() As Byte = System.IO.File.ReadAllBytes("C:\WINDOWS\system32\calc.exe")
Dim base64 As String = Convert.ToBase64String(bin)
'文字列→バイナリ復元 
Dim bin2() As Byte = Convert.FromBase64String(base64)
投稿者 O-157  (その他) 投稿日時 2011/3/9 14:48:07
ありがとうございました!!魔界の仮面弁士さんの回答のお陰で解決しましたが、他の方々の回答もとても参考になりました。ありがとうございます!!