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

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

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

Re[4]: 文字列をbyte型配列に変換した時の配列長


(過去ログ 48 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■26292 / inTopicNo.1)  文字列をbyte型配列に変換した時の配列長
  
□投稿者/ kakel (5回)-(2008/10/06(Mon) 16:18:47)

分類:[C#] 

前回記述した訂正版です。
あちらをみられた方、失礼しました。新規投稿させて頂きますので、再度お願い致します。
初めて見られる方はそのまま、読んで下さい。

VisualStudio2005のC#で開発しています。
文字列からbyte型配列に変換する際に、変換前と変換後で配列の長さが変わってしまいますが、
これは仕様でしょうか?
長さを変えずにできないものでしょうか?
以下の例は2つのファイルに記述したものですが、namespaceは同じです。

====Main.csで定義したCでいうグローバル変数みたいに使いまわす定数と変数====ここから
static public class GblConst
{
   public const int MAX = 3;
   :(省略)
   public const int LEN = 256;
}

static public class GblVar
{
    public class ProSet
    {
        static public byte bMax;
        :(省略)
        static public byte[] bPro = new byte[GblConst.LEN];
    }
}
====Main.csで定義したCでいうグローバル変数みたいに使いまわす定数と変数====ここまで

====Conv.cs実際に処理が行われるソース=====================================ここから
private bool bConv()
{
    :(省略)
    szPro = @"C:\テスト\テスト.pro";                                        ←Debug:GblVar.ProSet.bProの配列長は256
    GblVar.ProSet.bPro = Encoding.GetEncoding("Shift_JIS").GetBytes(szPro); ※ここで配列長が変化?

    return true;                                                            ←Debug:GblVar.ProSet.bProの配列長が20
}
====Conv.cs実際に処理が行われるソース=====================================ここまで

Conv.csの後、バイナリファイルに書込みをしたいのですが、

fs.Write(GblVar.ProSet.bPro, 0, GblVar.ProSet.bPro.Length);
とすると配列長が変化しているので、固定長で(NULL埋めしたい)書込みができません。
また、当然ですが、
fs.Write(GblVar.ProSet.bPro, 0, 256);とすると、例外が発生し、
「配列のオフセット及び長さが範囲を超えているか、カウンタが〜」のエラーがでてしまいます。

よろしくお願いします。


引用返信 編集キー/
■26293 / inTopicNo.2)  Re[1]: 文字列をbyte型配列に変換した時の配列長
□投稿者/ も (48回)-(2008/10/06(Mon) 16:36:45)
No26292 (kakel さん) に返信
> static public byte[] bPro = new byte[GblConst.LEN];
ここで作られた new byte[GblConst.LEN] は256バイト長のbyte配列(仮に名前を hoge)で,

> szPro = @"C:\テスト\テスト.pro"; ←Debug:GblVar.ProSet.bProの配列長は256
> GblVar.ProSet.bPro = Encoding.GetEncoding("Shift_JIS").GetBytes(szPro); ※ここで配列長が変化?
ここで作られた Encoding.GetEncoding("Shift_JIS").GetBytes(szPro) はまた別のbyte配列(こっちは piyo)になります.

bPro へ256バイト長の長さの配列である hoge を代入していますが,
その後,bPro へ別の配列(piyo)を代入しているため,bPro を参照すると別物になるというわけです.
(つまり,"長さが変化したと"捉えていらっしゃいますが別物です)

> Conv.csの後、バイナリファイルに書込みをしたいのですが、
>
> fs.Write(GblVar.ProSet.bPro, 0, GblVar.ProSet.bPro.Length);
> とすると配列長が変化しているので、固定長で(NULL埋めしたい)書込みができません。
例えば
byte[] byte256 = new byte[256];
byte[] enc = Encoding.GetEncoding("Shift_JIS").GetBytes(szPro);
Array.copy(enc, byte256, enc.length < 256 ? enc.length : 256);
の様に,明示的に長さ256バイトの配列へコピーするなどして,0埋めしてはいかがでしょうか?
引用返信 編集キー/
■26294 / inTopicNo.3)  Re[2]: 文字列をbyte型配列に変換した時の配列長
□投稿者/ Algol (29回)-(2008/10/06(Mon) 16:45:57)
バイト長が必要ならば、GetByteCountメソッドを使うと良いです。

Encoding sjisEncoding = Encoding.GetEncoding("Shift_JIS");
int sjisByteCount = sjisEncoding.GetByteCount("もじれつ");

引用返信 編集キー/
■26295 / inTopicNo.4)  Re[3]: 文字列をbyte型配列に変換した時の配列長
□投稿者/ ぽぴ王子 (398回)-(2008/10/06(Mon) 16:50:26)
ぽぴ王子 さんの Web サイト
No26292 (kakel さん) に返信

> VisualStudio2005のC#で開発しています。
> 文字列からbyte型配列に変換する際に、変換前と変換後で配列の長さが変わってしまいますが、
> これは仕様でしょうか?
> 長さを変えずにできないものでしょうか?
> 以下の例は2つのファイルに記述したものですが、namespaceは同じです。

正直なところ、何が聞きたいのかよくわかりません。
何がおかしくなっていて、何を解決したいのかをキチンと論理立てて説明することが必要です。
(そのためには必要最小限の再現性を持ったコードを提示することもあります)

結局のところ別ソースとかそういったことは *まったく* 関係なくて

>         static public byte[] bPro = new byte[GblConst.LEN];

で定義した bPro が

>     szPro = @"C:\テスト\テスト.pro";                                        ←Debug:GblVar.ProSet.bProの配列長は256
>     GblVar.ProSet.bPro = Encoding.GetEncoding("Shift_JIS").GetBytes(szPro); ※ここで配列長が変化?

というコードを通ったら、GblVar.Proset.bPro.Length が GblConst.LEN でなくなってしまった!
とおっしゃりたいわけですよね。

回答者にそこまでの解釈を要求するような質問は、回答がつきにくいと思います。

また

> 「配列のオフセット及び長さが範囲を超えているか、カウンタが〜」のエラーがでてしまいます。

エラーメッセージも正しく複写した方がよろしいです。あなたは何度も見てわかっているかもしれませんが
このエラーの省略されている部分に大事なヒントが隠されていた場合、それを省略してしまったために
回答が得られないかもしれません。



で、本題。

この場合「配列長が変化している」のではなく、配列そのものが GetBytes の戻り値によって置き換わっています。
なので、長さが GblConst.LEN でなくなっているのは当然です。

> fs.Write(GblVar.ProSet.bPro, 0, GblVar.ProSet.bPro.Length);
> とすると配列長が変化しているので、固定長で(NULL埋めしたい)書込みができません。

ということから、GblConst.LEN バイトのバイナリを出力したいのだと推測しますが、これでは無理ですね。
一度 GetBytes で得られた配列を GblConst.LEN の長さの配列にコピーする( Array.Copy )か、GetBytes
で得られた配列を fs.Write を使用して書き込んだ後、残りの長さ分の 0x00 を出力するかになるのでは
ないでしょうか。

# と書いていたら「も」さんと「Algol」さんに先を越されてしまった

引用返信 編集キー/
■26296 / inTopicNo.5)  Re[3]: 文字列をbyte型配列に変換した時の配列長
□投稿者/ Algol (30回)-(2008/10/06(Mon) 16:57:25)
もさんのほうが分かりやすくかかれてますね。
私のは、ちょっと的外れですな(汗
引用返信 編集キー/
■26305 / inTopicNo.6)  Re[4]: 文字列をbyte型配列に変換した時の配列長
□投稿者/ kakel (6回)-(2008/10/06(Mon) 19:02:43)
皆様、回答ありがとうございます。
無事NULL埋めできました。

256バイトと20バイトの別々の実体があって、代入したせいで、参照先が異なっていたから。
ですね。

結局、グローバル変数として扱うクラス中のbyte配列をstringで保持して
(ファイルオープン時NULLがはいってしまうとエラーになるから)使いまわすようにしました。
実際のバイナリファイルライトは、byte配列でライトする、もさんに提供頂きました配列コピー
のやり方を採用させて頂くことで対応できました。ありがとうございました。
ファイル長オーバーの処理は入力終了時にメッセージ表示させて対応することにしました。

ありがとうございました。解決とさせて頂きます。

新たに「Cでいう構造体で一括でライトするには?(以下のように)」
という新たな疑問が沸いてきましたが、こちらはまた別途調べてみようと思います。
typedef struct DAT_TAG {
    int a;
    int b;
    int c;
    int d;
    char szFile[256];
}DAT;

DAT stDat;

〜データセット省略〜
hFbin = CreateFile( szWriteFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL );
WriteFile( hFbin, &stDat, sizeof(DAT), &lWriteLen, NULL );

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -