C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

Byte配列→文字列→Byte配列の方法策 /io (18/04/16(Mon) 13:54) #87146
Re[1]: Byte配列→文字列→Byte配列の方法策 /furu (18/04/16(Mon) 14:21) #87147
Re[1]: Byte配列→文字列→Byte配列の方法策 /魔界の仮面弁士 (18/04/16(Mon) 15:18) #87148
Re[1]: Byte配列→文字列→Byte配列の方法策 /魔界の仮面弁士 (18/04/16(Mon) 16:50) #87149
  └ Re[2]: Byte配列→文字列→Byte配列の方法策 /io (18/04/16(Mon) 17:47) #87150
    └ Re[3]: Byte配列→文字列→Byte配列の方法策 /魔界の仮面弁士 (18/04/16(Mon) 19:47) #87151
      └ Re[4]: Byte配列→文字列→Byte配列の方法策 /io (18/04/17(Tue) 09:03) #87155


親記事 / ▼[ 87147 ] ▼[ 87148 ] ▼[ 87149 ]
■87146 / 親階層)  Byte配列→文字列→Byte配列の方法策
□投稿者/ io (1回)-(2018/04/16(Mon) 13:54:46)

分類:[.NET 全般] 

現在困っていて教えてください

あるByte配列をList of Tでリスト作成して、そのリストを使って色々しているのんですが

Byte配列を文字列に変更し、一旦テキストへファイルへ保存
読み込んで、またByte配列に戻したいんですが
これができません

現在Listは

count0
10
20
11
15
FF
count1
10
.
.
とあります

これを一旦文字列配列に直します
01,10 20 11 15 FF
02,10 20 ・・・・

というのをテキストで作成し
またreadalllineで string配列に戻し
byteListへ戻したいんですが ここができないです

流れとして
@ Private recive As New List(Of Byte()) で リストを作成
A ここに recive.Add(Byte配列)を入れていく
Brecive(Index)をある分だけ、string変換
Cstrをテキスト保存
Dファイルからstring配列(Load_str)に読み込み
Eload_strをまた新しいbyte配列へ変換
Frecive.Add(New Byte)





Dim load As String() = File.ReadAllLines("C\テスト\test.csv", enco)

Dim bytedata As Byte()
bytedata = New Byte() {}

For i As Integer = 0 To load.Length - 1
bytedata(i) = CByte(Convert.ToInt32(load(i), 16))
Next

コンバートすればいけるかな思いましたが
文字列の終わりに、追加の解析できない文字がありました。エラーがでます

そもそも、やり方が間違ってるのかしらべたんですが
わからずこちらで、ご質問させていただきました。

よろしくお願い致します。

[ □ Tree ] 返信 編集キー/

▲[ 87146 ] / 返信無し
■87147 / 1階層)  Re[1]: Byte配列→文字列→Byte配列の方法策
□投稿者/ furu (165回)-(2018/04/16(Mon) 14:21:17)
No87146 (io さん) に返信
> bytedata(i) = CByte(Convert.ToInt32(load(i), 16))
Byteを文字列にしたので
1バイト→2文字だよね

load(i)だと1文字分しかないような
[ 親 87146 / □ Tree ] 返信 編集キー/

▲[ 87146 ] / 返信無し
■87148 / 1階層)  Re[1]: Byte配列→文字列→Byte配列の方法策
□投稿者/ 魔界の仮面弁士 (1643回)-(2018/04/16(Mon) 15:18:41)
2018/04/16(Mon) 16:18:23 編集(投稿者)

No87146 (io さん) に返信
> あるByte配列をList of Tでリスト作成して、そのリストを使って色々しているのんですが
文字列化する意図が分からなかったのですが、File.ReadAllBytes / File.WriteAllBytes を使って、
テキストではなく、バイナリとして保持する…というわけにはいかないのですね?


> Byte配列を文字列に変更し、一旦テキストへファイルへ保存
Convert クラスの ToBase64String / FromBase64String メソッドでは駄目でしょうか?

io さんがやろうとしている方法(いわゆる hexString)では、
テキスト化に伴い、データ量が 2 倍(200%)に増加しますが、
上記(BASE64)の場合は 4/3 倍(133%) で済みます。



> @ Private recive As New List(Of Byte()) で リストを作成
> A ここに recive.Add(Byte配列)を入れていく
recive ではなく
receive なのでは、という点はさておき。

上記の変数宣言が、
 Private recive As New List(Of Byte) '(a)
ではなく、
 Private recive As New List(Of Byte()) '(b)
になっていますが、これは間違いないのですね?


(a) の場合は、単一のバイナリを蓄えるもので、たとえば
 recive.AddRange(New Byte() { &H01, &H03, &H05, &H07 })
 recive.AddRange(New Byte() { &H09, &H0B, &H0D, &H0F, &H11, &H13 })
などのように使うもの。この場合、recive.Count は 10 を返します。

(b) の場合は、複数のバイナリを蓄えるもので、たとえば
 recive.Add(New Byte() { &H01, &H03, &H05, &H07 })
 recive.Add(New Byte() { &H09, &H0B, &H0D, &H0F, &H11, &H13 })
などのように使うものですね。この場合、recive.Count は 2 を返し、
recive(0).Length は 4 を返し、recive(1).Length は 6 を返します。



> Brecive(Index)をある分だけ、string変換
> Cstrをテキスト保存
VB には「Str 関数」が存在するので、str という名の変数は避けた方が良いですよ。
とりあえず、ここでいう recive(Index) が、上記 (b) を表すのであれば、
 Dim str1 As String = BitConverter.ToString(recive(0)).Replace("-", "")
 Dim str2 As String = BitConverter.ToString(recive(1)).Replace("-", "")
とすることで、
 Dim str1 As String = "0103050709"
 Dim str2 As String = "0B0D0F1113"
という結果を得ることが出来ます。
(Replace しなかった場合には、2 文字ごとに "-" が入ります)


> Dファイルからstring配列(Load_str)に読み込み
Cの str との関係性が分かりませんが、これが
> Dim load As String() = File.ReadAllLines("C\テスト\test.csv", enco)
の部分ということでしょうか。

だとすると、C:\テストではなく C\テストになっていますが、間違いないでしょうか。
また、一括読み込みのための File.ReadAllText や ReadAllBytes を使わず、
行単位読み込みの File.ReadAllLines を使っているのは意図的なものでしょうか。


> Eload_strをまた新しいbyte配列へ変換
元はバイナリであるはずの csv ファイルを、テキストデータとして文字列にデコードし、
それを再度バイナリデータに、別の形式で再エンコードするという流れなのですか?
回りくどい作業が行われているように思うのですが、
本当にその手順は必要なものなのでしょうか。


> Frecive.Add(New Byte)
ここの説明が、先の説明と矛盾していますね。

recive.Add(New Byte() {}) なら、Private recive As New List(Of Byte()) ですし、
recive.Add(New Byte()) なら、Private recive As New List(Of Byte) のはず。


> Dim load As String() = File.ReadAllLines("C\テスト\test.csv", enco)
ちなみに File.ReadAllLines メソッドは、
「改行が、レコードとレコードの間に配置されるタイプの CSV テキスト」と
「改行が、各レコードの末尾に配置されるタイプの CSV テキスト」を
区別できませんのでご注意ください。

具体的には、CSV の中身が
「あい,うえ{改行}かき,くけ」
「あい,うえ{改行}かき,くけ{改行}」
のいずれのファイルを読み取った場合も、load.Length が 2 になってしまうということです。

そのため、この方法でファイルを読み取った場合は、元のファイルを
完全再現させることができませんのでご注意ください。


> For i As Integer = 0 To load.Length - 1
> bytedata(i) = CByte(Convert.ToInt32(load(i), 16))
> Next
上記で i = 0 のときに、load(i) に格納されている文字列は何でしょうか?

load(i) = "00" や load(i) = "FF" ならば、
CByte まで成功します。

load(i) = "0100" や load(i) = "0B0D0F11" ならば、
ToInt32 は成功しますが、CByte の部分で失敗します。

load(i) = "" や load(i) = "0B0D0F1113" だった場合、
CByte はおろか、ToInt32 さえ失敗するでしょう。


この部分だけを見れば、行単位で処理しようとするのではなく、
hexString を 2 文字ずつ変換してやれば復元はできるでしょうが、
bytedata() のインデックスは「バイト位置」で
load() のインデックスは「行番号」なのですから、どちらにしても
そもそもの変換ルールに問題があるように見えます。


> そもそも、やり方が間違ってるのかしらべたんですが
> わからずこちらで、ご質問させていただきました。

やりたいことを、もう一度整理してみてください。

数行の短い CSV ファイルを用意し、
それぞれの変数に、どのような値が入ることを期待しているのかを
再度考え直してみることをお奨めします。
[ 親 87146 / □ Tree ] 返信 編集キー/

▲[ 87146 ] / ▼[ 87150 ]
■87149 / 1階層)  Re[1]: Byte配列→文字列→Byte配列の方法策
□投稿者/ 魔界の仮面弁士 (1644回)-(2018/04/16(Mon) 16:50:37)
No87146 (io さん) に返信
> これを一旦文字列配列に直します
> 01,10 20 11 15 FF
> 02,10 20 ・・・・
最初はカンマ区切り、2 つ目以降はスペース区切りなのですね。

最初の 2 文字 + カンマは、行番号を表すのでしょうか。
(99 行目あるいは &HFF 行目を超えたときにどうなるのだろう…?)

それとも、カンマでも空白でも許容する、ということなのでしょうか。


> というのをテキストで作成し
ここでいう「テキスト」が何を指しているのか読み取れませんでした。
先ほどの「文字列」とは別のものなのですよね?


> またreadalllineで string配列に戻し
> byteListへ戻したいんですが ここができないです
文字列とバイナリを行ったり来たりしていて、処理の流れが
どうにも把握できていないのですが、ひとまず、こんな手順ではどうでしょうか。


Dim src As String() = {"01,10 20 11 15 FF", "02,10 20"}
Dim byteList As New List(Of Byte())

byteList.Clear()
For Each line As String In src
 '16進数文字列以外は捨てる
 line = New String(line.ToUpper().Where(Function(c) c Like "[0-9A-F]").ToArray())

 Using ms As New MemoryStream()
  '2文字ずつ切り出す
  For i As Integer = 0 To line.Length - 1 Step 2
   ms.WriteByte(Convert.ToByte(line.Substring(i, 2), 16))
  Next

  'byteList に詰める
  byteList.Add(ms.ToArray())
 End Using
Next
[ 親 87146 / □ Tree ] 返信 編集キー/

▲[ 87149 ] / ▼[ 87151 ]
■87150 / 2階層)  Re[2]: Byte配列→文字列→Byte配列の方法策
□投稿者/ io (2回)-(2018/04/16(Mon) 17:47:12)
2018/04/16(Mon) 17:53:11 編集(投稿者)
2018/04/16(Mon) 17:53:09 編集(投稿者)

詳しく説明して頂き 感謝いたします
まだまだ勉強不足を痛感しています

そもそも何をしたいか?
も書いていないの意味がわかりませんよね。。

Byte配列は、シリアル通信で入ってくるデータで
受信すると、イベントチェンジプロシージャに入っていき
そのたびにListに追加しています

byte配列に対して、IDが振って

Dictionaryで持っていて

A,Byte配列1
B,Byte配列2
C,Byte配列3

Aなら1というふうにプログラム上で書いていましたが
ユーザー側が、Aにデータを追加したいとか
出た案件で、簡単にユーザー側が使えるようにしたかったので
txt,csvなどで管理するために
わざわざテキストへ。。。と考えておりました

しかし、自分がまだbyteに対して知識不足のため明らかに無駄な事をしているのが
皆さんの教えでわかりました

A,Byte配列1,Byte配列4
B,Byte配列2
C,Byte配列3

4を簡単に追加できるようにプログラムでして
外に保存し

A,Byte配列1
B,Byte配列2,Byte配列4
C,Byte配列3

とか

A,Byte配列2
B,Byte配列1,Byte配列4
C,Byte配列3

入れ替えたりをユーザー側で、できるような
アプリを作成しようとしていました

writebyteでやったほうが合理的ですかね?

[ 親 87146 / □ Tree ] 返信 編集キー/

▲[ 87150 ] / ▼[ 87155 ]
■87151 / 3階層)  Re[3]: Byte配列→文字列→Byte配列の方法策
□投稿者/ 魔界の仮面弁士 (1645回)-(2018/04/16(Mon) 19:47:27)
No87150 (io さん) に返信
> Byte配列は、シリアル通信で入ってくるデータで

であれば、元データはバイナリであって、文字列では無いのでは…。


> 受信すると、イベントチェンジプロシージャに入っていき
> そのたびにListに追加しています
> byte配列に対して、IDが振って

それが最初の質問の
>> 01,10 20 11 15 FF
>> 02,10 20 ・・・・
における "01," や "02," なのですね?

でもって、ID=01 と ID=02 は別々のデータであり、
連結して一つにまとめるわけではない、と。


> Dictionaryで持っていて
> A,Byte配列1
> B,Byte配列2
> C,Byte配列3
1 ではなく A になっている点が読み取れませんでしたが、
ここでいう ID は連番というよりも、種別コードみたいなものなのかな…。


> Aなら1というふうにプログラム上で書いていましたが
> ユーザー側が、Aにデータを追加したいとか
管理を Dictionary(Of 種別, List(Of Byte)) あたりにしておけば、
 dict(種別.A).AddRange( 追加したいバイナリ )
とか、
 Dim bin As Byte() = dict(種別.B).ToArray()
のような使い方ができそうです。


> 出た案件で、簡単にユーザー側が使えるようにしたかったので
> txt,csvなどで管理するために
その csv がどういう使われ方をしているのか分からないのですが、
今回問題になっているのはシリアル通信の部分ではなく、
txt ファイルの内容をバイナリで読み取るところなのですね?


ファイルから読み取られた
 Dim src As String = "10 20 11 15 FF"
なデータを変換して、
 Dim dst As Byte() = { &H10, &H20, &H11, &H15, &HFF }
にするのは、変換用に
 Function ToBinary( src As String) As Byte()
なメソッドを一つ作ってやれば済む話ですし、実装例として
No87149 とか No75726 とかを真似れば良いはず。


あとは、先頭の ID 部分をどう管理するのかによって、
コーディングが変わってくることになるかと。


> 外に保存し
「シリアル通信」でもデータを受け取り、「ファイル」でも受け取るのですか?

どちらのデータがより優先させるのか、
ファイルを開いている間に届いたシリアル通信のデータはどのように扱われるのか、
そのファイルを「読み取る」だけでなく「書き込む」こともするのなら、排他制御の問題は、
などなど、話が複雑化するような気がします…が、こちらはデータの流れを
把握しているわけではないので、どうすべきかという点にまでは言及し難いです。
[ 親 87146 / □ Tree ] 返信 編集キー/

▲[ 87151 ] / 返信無し
■87155 / 4階層)  Re[4]: Byte配列→文字列→Byte配列の方法策
□投稿者/ io (3回)-(2018/04/17(Tue) 09:03:24)
No87151 (魔界の仮面弁士 さん) に返信
> ■No87150 (io さん) に返信

> それが最初の質問の
> >> 01,10 20 11 15 FF
> >> 02,10 20 ・・・・
> における "01," や "02," なのですね?
>
> でもって、ID=01 と ID=02 は別々のデータであり、
> 連結して一つにまとめるわけではない、と。
>
その通りでございます
ID=01とそれぞれ違う役割があるので
ID=01に 0 20 11 15 FF Byte配列設定をしています

>>C,Byte配列3
> 1 ではなく A になっている点が読み取れませんでしたが、
> ここでいう ID は連番というよりも、種別コードみたいなものなのかな…。

わかりにくくてすいません、そのとおりです
種別コードと思ってください。


>>Aなら1というふうにプログラム上で書いていましたが
>>ユーザー側が、Aにデータを追加したいとか
> 管理を Dictionary(Of 種別, List(Of Byte)) あたりにしておけば、
>  dict(種別.A).AddRange( 追加したいバイナリ )
> とか、
>  Dim bin As Byte() = dict(種別.B).ToArray()
> のような使い方ができそうです。
>

これはやったことがないなので
試してみます!

> その csv がどういう使われ方をしているのか分からないのですが、
> 今回問題になっているのはシリアル通信の部分ではなく、
> txt ファイルの内容をバイナリで読み取るところなのですね?
>
簡単に言えば、システム作成側はByteなりどーいうものかなんとなくわかるのですが
あくまでユーザーは一切わからない人達です

ユーザーはID側だけ設定して
それに対し、登録?みたいな感じで、Byteをシリアルで読み込んでます

>
> ファイルから読み取られた
>  Dim src As String = "10 20 11 15 FF"
> なデータを変換して、
>  Dim dst As Byte() = { &H10, &H20, &H11, &H15, &HFF }
> にするのは、変換用に
>  Function ToBinary( src As String) As Byte()
> なメソッドを一つ作ってやれば済む話ですし、実装例として
> No87149 とか No75726 とかを真似れば良いはず。

ありがとうございます
変換は既にできています

>
>>外に保存し
> 「シリアル通信」でもデータを受け取り、「ファイル」でも受け取るのですか?
>
> どちらのデータがより優先させるのか、
> ファイルを開いている間に届いたシリアル通信のデータはどのように扱われるのか、
> そのファイルを「読み取る」だけでなく「書き込む」こともするのなら、排他制御の問題は、
> などなど、話が複雑化するような気がします…が、こちらはデータの流れを
> 把握しているわけではないので、どうすべきかという点にまでは言及し難いです。

簡単な話

A,10 20 11 15 FF
B,10 20 11 15 FF

と Txtファイルに書き込ませて

ABを逆にしたり
A,10 20 11 15 FF,10 20 11 15 FF
追加したり

Byteを文字列に見せて
コピペすればいいですよ的なものにしたかったです

あとはプログラムが変換 dic登録をして
システムへとつなげるみたいな感じで

システム × ファイル ユーザー側
システム = ファイル 作成側



ユーザーはファイルだけいじるだけにしたかったのが目的となります







[ 親 87146 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -