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

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

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

Re[10]: C# テキストファイルのデータをコンボボックス項目へ


(過去ログ 129 を表示中)

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

■76418 / inTopicNo.1)  C# テキストファイルのデータをコンボボックス項目へ
  
□投稿者/ ゆーきゃん (7回)-(2015/07/09(Thu) 16:10:52)

分類:[C#] 


いつも大変お世話になっております。
質問よろしいでしょうか?

visualC#でコンボボックスにテキストファイルの値を項目として追加しようとしております。

テキストファイルの中身は以下の通りです。

data.txt---------------------------------
1
20
2C-60x30x10x1.6
H-100x50x5x5x7x8
H-200x100x5.5x8x8
------------------------------------------

この際、「H」から始まる文字のみをコンボボックスに追加したいのですが、そのように制御することは可能でしょうか?

また、H-100x50x5x5x7x8をコンボボックスで選択した際に、

string moji = "H";
int a1 = 100;
int a2 = 50;
int a3 = 5;
int a4 = 5;
int a5 = 7;
int a6 = 8;

といった形に変数へ割り当てていきたいのですが、こちらも可能でしょうか?


現状のプログラムは以下の通りです。

private void test_form_Load(object sender, EventArgs e)
{
//コンボボックスをクリアする
tanbu_cb.Items.Clear();

//テキストファイルを開く
StreamReader tanbu = File.OpenText(@"c:\data\data.txt");

//再描画しないようにする(ちらつき防止)
tanbu_cb.BeginUpdate();

//テキストファイルの最後までループ
while ((line = tanbu.ReadLine()) != null)
{
//コンボボックスに1行ずつ挿入する
tanbu_cb.Items.Add(line);
}
//再描画するようにする
tanbu_cb.EndUpdate();

//コンボボックスの0行目を表示させる
tanbu_cb.SelectedIndex = -1;
}


宜しければご教授頂けないでしょうか。
よろしくお願い致します。


引用返信 編集キー/
■76419 / inTopicNo.2)  Re[1]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ Hongliang (322回)-(2015/07/09(Thu) 16:17:21)
> この際、「H」から始まる文字のみをコンボボックスに追加したいのですが、そのように制御することは可能でしょうか?

stringのStartsWithメソッドを使って判定すればいいでしょう。

> また、H-100x50x5x5x7x8をコンボボックスで選択した際に、
>
> string moji = "H";
> int a1 = 100;
(snip)
> int a6 = 8;
>
> といった形に変数へ割り当てていきたいのですが、こちらも可能でしょうか?

stringのSplitメソッドおよびInt32.Parseメソッド辺りを使えば良いでしょう。
引用返信 編集キー/
■76421 / inTopicNo.3)  Re[2]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ ゆーきゃん (8回)-(2015/07/09(Thu) 18:57:18)
No76419 (Hongliang さん) に返信
>>この際、「H」から始まる文字のみをコンボボックスに追加したいのですが、そのように制御することは可能でしょうか?
>
> stringのStartsWithメソッドを使って判定すればいいでしょう。
>
>>また、H-100x50x5x5x7x8をコンボボックスで選択した際に、
>>
>>string moji = "H";
>>int a1 = 100;
> (snip)
>>int a6 = 8;
>>
>>といった形に変数へ割り当てていきたいのですが、こちらも可能でしょうか?
>
> stringのSplitメソッドおよびInt32.Parseメソッド辺りを使えば良いでしょう。


素早いお返事ありがとうございます。

StartsWithメソッドを使用することで、思い通りの結果を出力することができました。
StartsWithメソッド自体の存在を初めて知りました。とても便利なメソッドですね!
教えて頂きありがとうございます。


Splitメソッドを使用することで対応できそうですね。
こちらのメソッドも初めて知りました。教えて頂きありがとうございます。
ただ、ちょっと使い方に慣れてないせいか、なかなか思い通りの結果を出力できずにいます。
色々なサイトを参考にしながら、引き続きプログラミング作業を行ってきます。


引用返信 編集キー/
■76422 / inTopicNo.4)  Re[1]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ 魔界の仮面弁士 (396回)-(2015/07/09(Thu) 19:04:51)
No76418 (ゆーきゃん さん) に返信
> また、H-100x50x5x5x7x8をコンボボックスで選択した際に、
> string moji = "H";
> int a1 = 100;
> int a2 = 50;
> int a3 = 5;
> int a4 = 5;
> int a5 = 7;
> int a6 = 8;
> といった形に変数へ割り当てていきたいのですが、

data.txt には、
 「H-200x100x5.5x8x8」
のように、数値が 5 つで、しかも一つは小数という項目もありましたが、
「int a3」や「int a6」にはどのような値が入って欲しいのでしょうか?


> こちらも可能でしょうか?
int 型の a1〜a6 の部分を変形して、
decimal 型の a[0]〜a[n] にしてみました。


// using System;
// using System.IO;
// using System.Collections.ObjectModel;
// using System.Linq;
// using System.Windows.Forms;

private void Form1_Load(object sender, EventArgs e)
{
  // H で始まる行のみを読み込む
  comboBox1.DataSource = File.ReadLines(@"C:\temp\data.txt")
    .Where(s => s.StartsWith("H")).ToArray();
}

// 選択された内容を管理するクラス
Item selectedItem = null;
class Item
{
  public string Moji;
  public ReadOnlyCollection<decimal> a;

  public Item(string src)
  {
    var block = src.Split('-');
    this.Moji = block[0];
    this.a = Array.AsReadOnly(block[1].Split('x').Select(v => Convert.ToDecimal(v)).ToArray());
  }
}

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
  string selectedText = comboBox1.GetItemText(comboBox1.SelectedItem);
  if (string.IsNullOrEmpty(selectedText))
  {
    selectedItem = null;

    label1.Text = label2.Text = label3.Text = label4.Text = "";
  }
  else
  {
    selectedItem = new Item(selectedText);

    label1.Text = selectedItem.Moji;
    label2.Text = selectedItem.a[0].ToString();
    label3.Text = selectedItem.a[1].ToString();
    label4.Text = selectedItem.a[2].ToString();
    
  }
}
引用返信 編集キー/
■76424 / inTopicNo.5)  Re[2]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ ゆーきゃん (9回)-(2015/07/10(Fri) 09:13:51)
No76422 (魔界の仮面弁士 さん) に返信
> ■No76418 (ゆーきゃん さん) に返信

> data.txt には、
>  「H-200x100x5.5x8x8」
> のように、数値が 5 つで、しかも一つは小数という項目もありましたが、
> 「int a3」や「int a6」にはどのような値が入って欲しいのでしょうか?


お返事ありがとうございます。
仰る通りですね。
int型では小数に対応できませんので、double型に変更いたしました。
ご指摘ありがとうございます。


> int 型の a1〜a6 の部分を変形して、
> decimal 型の a[0]〜a[n] にしてみました。
>
>
> // using System;
> // using System.IO;
> // using System.Collections.ObjectModel;
> // using System.Linq;
> // using System.Windows.Forms;
>
> private void Form1_Load(object sender, EventArgs e)
> {
>   // H で始まる行のみを読み込む
>   comboBox1.DataSource = File.ReadLines(@"C:\temp\data.txt")
>     .Where(s => s.StartsWith("H")).ToArray();
> }
>
> // 選択された内容を管理するクラス
> Item selectedItem = null;
> class Item
> {
>   public string Moji;
>   public ReadOnlyCollection<decimal> a;
>
>   public Item(string src)
>   {
>     var block = src.Split('-');
>     this.Moji = block[0];
>     this.a = Array.AsReadOnly(block[1].Split('x').Select(v => Convert.ToDecimal(v)).ToArray());
>   }
> }
>
> private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
> {
>   string selectedText = comboBox1.GetItemText(comboBox1.SelectedItem);
>   if (string.IsNullOrEmpty(selectedText))
>   {
>     selectedItem = null;
>
>     label1.Text = label2.Text = label3.Text = label4.Text = "";
>   }
>   else
>   {
>     selectedItem = new Item(selectedText);
>
>     label1.Text = selectedItem.Moji;
>     label2.Text = selectedItem.a[0].ToString();
>     label3.Text = selectedItem.a[1].ToString();
>     label4.Text = selectedItem.a[2].ToString();
>     
>   }
> }

わざわざプログラムソースを掲示して頂きありがとうございます。
大変助かりました。参考にさせて頂きます。
自分が知らない機能がたくさん組み込まれていますので、
調べながら理解できるようにしていきたいと思っております。

引用返信 編集キー/
■76425 / inTopicNo.6)  Re[3]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ ゆーきゃん (10回)-(2015/07/10(Fri) 09:50:27)
皆様のアドバイスのおかげで何とか形になりました。

何かお役に立つかわかりませんが、自分が作ったプログラムソースも提示させて頂きます。


private void test_form_Load(object sender, EventArgs e)
{

//コンボボックスをクリアする
tanbu_cb.Items.Clear();

//テキストファイルを開く
StreamReader tanbu = File.OpenText(@"c:\data\data.txt");

//再描画しないようにする(ちらつき防止)
tanbu_cb.BeginUpdate();

string[] buzai = File.ReadAllLines(@"c:\data\BMASTER.Dat");
int n = 0;

//テキストファイルの最後までループ
while ((line = tanbu.ReadLine()) != null)
{
buzai[n] = line;

// 先頭文字が"H"の場合、コンボボックスに追加する。
if (buzai[n].StartsWith("H"))
{
//コンボボックスに1行ずつ挿入する
tanbu_cb.Items.Add(line);
}
n++;
}
//再描画するようにする
tanbu_cb.EndUpdate();
//コンボボックスの0行目を表示させる
tanbu_cb.SelectedIndex = -1;
}


string[] tanbu_buzai = new string[100];

string tanbu_moji;
double tanbu_a1;
double tanbu_a2;
double tanbu_a3;
double tanbu_a4;

int i=0;

private void tanbu_cb_SelectedIndexChanged(object sender, EventArgs e)
{
tanbu_buzai[i] = tanbu_cb.SelectedItem.ToString();
string[] buzai_kuwake = tanbu_buzai[i].Split('-','x');

for (int j = 0; j < buzai_kuwake.Length; j++ )
{
if (j == 0)
{
tanbu_moji = buzai_kuwake[j].ToString();
}

else if(j == 1)
{
tanbu_a1 = double.Parse(buzai_kuwake[j]);
}

else if (j == 2)
{
tanbu_a2 = double.Parse(buzai_kuwake[j]);
}

else if (j == 3)
{
tanbu_a3 = double.Parse(buzai_kuwake[j]);
}

else
{
tanbu_a4 = double.Parse(buzai_kuwake[j]);
}
}

i++;
}


至らない点が多々あると思いますが、一応起動確認もできました。
ここをこうするといいよといった箇所はありますでしょうか?


引用返信 編集キー/
■76426 / inTopicNo.7)  Re[4]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ 魔界の仮面弁士 (397回)-(2015/07/10(Fri) 11:33:03)
No76425 (ゆーきゃん さん) に返信
> ここをこうするといいよといった箇所はありますでしょうか?

あります。ソースコードを掲示板に貼るときは、
投稿モードを「図表モード」にしましょう。
そうすれば、インデントを崩すことなく投稿できますよ。



> //テキストファイルを開く
> StreamReader tanbu = File.OpenText(@"c:\data\data.txt");
開いたストリームを閉じ忘れているようです。
使用後に tanbu.Close(); を明記しましょう。

あるいは、内容を一括で読み取ってくれる File.ReadAllLines を使うのも
良いかと思います。これなら閉じる手間がかかりません。
もしくは、File.ReadLines メソッドを使うのも良いでしょうね。



> string[] buzai = File.ReadAllLines(@"c:\data\BMASTER.Dat");
この段階で、BMASTER.Dat の内容すべてが buzai に入りますよね。


> while ((line = tanbu.ReadLine()) != null)
> {
>   buzai[n] = line;
その内容を data.txt の内容で置き換えているようですが、
これは一体なんのために行っているのでしょうか?
BMASTER.Dat の利用目的が読み取れませんでした。


> else if(j == 1)
> {
>   tanbu_a1 = double.Parse(buzai_kuwake[j]);
> }
> else if (j == 2)
> {
>   tanbu_a2 = double.Parse(buzai_kuwake[j]);
> }
> else if (j == 3)
> {
>   tanbu_a3 = double.Parse(buzai_kuwake[j]);
> }
これだと、折角のループ処理が台無しです。
配列や List<> などを使いましょう。
引用返信 編集キー/
■76429 / inTopicNo.8)  Re[5]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ ゆーきゃん (12回)-(2015/07/10(Fri) 13:16:49)
No76426 (魔界の仮面弁士 さん) に返信
> ■No76425 (ゆーきゃん さん) に返信
>>ここをこうするといいよといった箇所はありますでしょうか?
>
> あります。ソースコードを掲示板に貼るときは、
> 投稿モードを「図表モード」にしましょう。
> そうすれば、インデントを崩すことなく投稿できますよ。

そのための図表モードだったのですね。
了解いたしました。


>>//テキストファイルを開く
>>StreamReader tanbu = File.OpenText(@"c:\data\data.txt");
> 開いたストリームを閉じ忘れているようです。
> 使用後に tanbu.Close(); を明記しましょう。
>
> あるいは、内容を一括で読み取ってくれる File.ReadAllLines を使うのも
> 良いかと思います。これなら閉じる手間がかかりません。
> もしくは、File.ReadLines メソッドを使うのも良いでしょうね。

ストリームを閉じていなくても特に不具合等確認できなかったのですが、
閉じないと不具合等が何か起こる場合があるということですね。
意識するようにいたします。
また、File.ReadAllLines 、File.ReadLines メソッドについても調べさせていただきます。




>
>>string[] buzai = File.ReadAllLines(@"c:\data\BMASTER.Dat");
> この段階で、BMASTER.Dat の内容すべてが buzai に入りますよね。

すいません。記入ミスしていました
string[] buzai = File.ReadAllLines(@"c:\data\data.txt");
でした。


>>while ((line = tanbu.ReadLine()) != null)
>>{
>>  buzai[n] = line;
> その内容を data.txt の内容で置き換えているようですが、
> これは一体なんのために行っているのでしょうか?
> BMASTER.Dat の利用目的が読み取れませんでした。

buzai[n] = line;
たしかに必要ないですね。
2度読み込んでしまっているような形になってしまっていますね。


>>else if(j == 1)
>>{
>>  tanbu_a1 = double.Parse(buzai_kuwake[j]);
>>}
>>else if (j == 2)
>>{
>>  tanbu_a2 = double.Parse(buzai_kuwake[j]);
>>}
>>else if (j == 3)
>>{
>>  tanbu_a3 = double.Parse(buzai_kuwake[j]);
>>}
> これだと、折角のループ処理が台無しです。
> 配列や List<> などを使いましょう。

自分もここが一番プログラムを書いていて引っかかっていたところです。
見栄え効率ともに悪いですよね。
もう少し調べて改善していきたいと思います。

的確なご指示ありがとうございます。

引用返信 編集キー/
■76430 / inTopicNo.9)  Re[6]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ 魔界の仮面弁士 (398回)-(2015/07/10(Fri) 13:41:36)
No76429 (ゆーきゃん さん) に返信
> ストリームを閉じていなくても特に不具合等確認できなかったのですが、
> 閉じないと不具合等が何か起こる場合があるということですね。

それでは実験。
ボタンとリストボックスを 2 つずつ用意し、下記を実行してみて下さい。

button1 は、data1.txt のストリームを Close していません。
button2 は、data2.txt を ReadAllLines で読み取っているコードです。


private void button1_Click(object sender, EventArgs e)
{
    listBox1.BeginUpdate();
    listBox1.Items.Clear();

    var stm = File.OpenText(@"c:\data\data1.txt");
    string line;
    while ((line = stm.ReadLine()) != null)
    {
        listBox1.Items.Add(line);
    }
    // stm.Close(); // 実験のため、あえて Close も Dispose も呼ばない

    listBox1.EndUpdate();
}

private void button2_Click(object sender, EventArgs e)
{
    var lines = File.ReadAllLines(@"c:\data\data2.txt");
    listBox2.DataSource = lines;
}

それぞれのボタンを押した後、エクスプローラーで、
data1.txt と data2.txt を、それぞれ別の名前に
リネームしてみてください。

閉じ忘れている data1.txt の方は、リネームに失敗してしまうかと思います。
(アプリを終了するなどすれば、リネームできるようになりますが)



> また、File.ReadAllLines 、File.ReadLines メソッドについても調べさせていただきます。
これらのメソッドでは、ファイルの開閉が自動的に行われますので、
Close を呼び出す必要がありません(というか呼び出せない)。


ReadAllLines メソッドは、ファイルの内容すべてを一度に読み取り、即座に閉じる機能。
その他の ReadAll 系メソッドも同様に、ファイル全体を一度に読み取り、即座に閉じます。


一方 ReadLines メソッドは、それを呼び出しただけではファイルは開かれません。(遅延実行)
呼び出した結果を foreach で列挙したり、上記のように .DataSource に割り当てたりすると
その時初めてファイルが開かれ、そして列挙が終了した時点で自動的に閉じられる仕組みです。


> すいません。記入ミスしていました
> string[] buzai = File.ReadAllLines(@"c:\data\data.txt");
> でした。
そうすると、StreamReder で開いていた
 StreamReader tanbu = File.OpenText(@"c:\data\data.txt");
の方は不要になりますね。

引用返信 編集キー/
■76431 / inTopicNo.10)  Re[7]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ ゆーきゃん (14回)-(2015/07/10(Fri) 15:19:42)
No76430 (魔界の仮面弁士 さん) に返信
> ■No76429 (ゆーきゃん さん) に返信
> 
> それでは実験。
> ボタンとリストボックスを 2 つずつ用意し、下記を実行してみて下さい。
> 
> button1 は、data1.txt のストリームを Close していません。
> button2 は、data2.txt を ReadAllLines で読み取っているコードです。
> 
> 
> private void button1_Click(object sender, EventArgs e)
> {
>     listBox1.BeginUpdate();
>     listBox1.Items.Clear();
> 
>     var stm = File.OpenText(@"c:\data\data1.txt");
>     string line;
>     while ((line = stm.ReadLine()) != null)
>     {
>         listBox1.Items.Add(line);
>     }
>     // stm.Close(); // 実験のため、あえて Close も Dispose も呼ばない
> 
>     listBox1.EndUpdate();
> }
> 
> private void button2_Click(object sender, EventArgs e)
> {
>     var lines = File.ReadAllLines(@"c:\data\data2.txt");
>     listBox2.DataSource = lines;
> }
> 
> それぞれのボタンを押した後、エクスプローラーで、
> data1.txt と data2.txt を、それぞれ別の名前に
> リネームしてみてください。
> 
> 閉じ忘れている data1.txt の方は、リネームに失敗してしまうかと思います。
> (アプリを終了するなどすれば、リネームできるようになりますが)
> 

なるほど。
確かに症状の方を確認できました。
.Close()の重要性が分かりました。



> これらのメソッドでは、ファイルの開閉が自動的に行われますので、
> Close を呼び出す必要がありません(というか呼び出せない)。
> 
> 
> ReadAllLines メソッドは、ファイルの内容すべてを一度に読み取り、即座に閉じる機能。
> その他の ReadAll 系メソッドも同様に、ファイル全体を一度に読み取り、即座に閉じます。
> 
> 
> 一方 ReadLines メソッドは、それを呼び出しただけではファイルは開かれません。(遅延実行)
> 呼び出した結果を foreach で列挙したり、上記のように .DataSource に割り当てたりすると
> その時初めてファイルが開かれ、そして列挙が終了した時点で自動的に閉じられる仕組みです。
> 

基本的には、File.OpenTextより、ReadAllLines メソッド等を使った方が間違えにくそうですね。とても参考になりました。
ありがとうございます。

引用返信 編集キー/
■76432 / inTopicNo.11)  Re[8]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ 魔界の仮面弁士 (399回)-(2015/07/10(Fri) 16:26:02)
ごめんなさい! ReadLines の動作について間違った説明をしていたので訂正します。


No76431 (ゆーきゃん さん) に返信
>>一方 ReadLines メソッドは、それを呼び出しただけではファイルは開かれません。(遅延実行)
すみません。上記は間違いで、呼び出した時点で開かれていました。
(列挙し終わったら自動的に閉じられる、という認識は正しい模様)


>>呼び出した結果を foreach で列挙したり、上記のように .DataSource に割り当てたりすると

先の例で使ったのは、.ReadLines ではなく .ReadAllLines でしたね。
.ReadLines の結果は .そもそも .DataSource には割り当てられません…失礼しました。

.ReadLines の結果を .DataSource に割り当てる場合には、
.ToArray か .ToList を併用することになります。


var data = File.ReadLines(@"C:\folder\file.txt");

// listBox1.DataSource = data;  // これは NG
listBox1.DataSource = data.ToArray();  // これなら OK


>>そして列挙が終了した時点で自動的に閉じられる仕組みです。
たとえば foreach を用いて
 foreach (var line in data)
 {
   listBox1.Items.Add(line);
 }
のようにループ処理を行った場合、ループ終了時点でファイルは自動で閉じられます。
あるいは .ToArray や .ToList で取得した場合も、自動的に閉じられます。

列挙終了後に、再度 data 変数を列挙しなおした場合は、
その時点でまたファイルが開きなおされ、列挙終了時に閉じられています。
引用返信 編集キー/
■76435 / inTopicNo.12)  Re[9]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ ゆーきゃん (15回)-(2015/07/10(Fri) 18:44:21)
No76432 (魔界の仮面弁士 さん) に返信
> ごめんなさい! ReadLines の動作について間違った説明をしていたので訂正します。

わざわざ訂正して頂きありがとうございます。
ReadLines の結果を .DataSource に割り当てる場合には、
.ToArray か .ToList を併用しなければいけないのですね。

自分なりに理解が追い付いてない箇所が多々あるので、もう一度調べ直してきます。

的確なお答えに頭が下がりっぱなしです。

引用返信 編集キー/
■76465 / inTopicNo.13)  Re[10]: C# テキストファイルのデータをコンボボックス項目へ
□投稿者/ ゆーきゃん (16回)-(2015/07/13(Mon) 08:50:25)
ある程度形になりましたので、これで次の段階に進みたいと思います。
魔界の仮面弁士様、いろいろとありがとうございました。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -