質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Q&A

解決済

1回答

1214閲覧

assetsフォルダのテキストファイルを読み込み、任意の部分だけを表示させたい

Yamade

総合スコア3

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

0グッド

0クリップ

投稿2022/01/05 05:56

編集2022/01/05 12:35

assetsフォルダのテキストファイルを読み込み、任意の部分だけを表示させたい

初心者ですが、はじめてここで質問させていただきます。
現在Android Studioを使い、言語はJavaでアプリ開発の練習を進めています。
作成中のアプリはassetsフォルダのなかに作成した、いくつかの国・都市名とそれぞれに割り当てられた4桁の番号が記されたテキストファイルを読み込み、アプリ画面にて4桁の番号を検索にかけることで、該当する国・都市名のみを表示させるというものです。

テキストファイルの読み込みや、検索番号を入力するところまではできているのですが、入力した番号とテキストファイル内の番号が一致していても一致していないことになるため悩んでいます。
助言をいただきたいですよろしくお願いします。

発生している問題・エラーメッセージ

2022-01-05 14:33:37.739 10566-10566/com.example.sampleMeibo I/System.out: 9999 2022-01-05 14:33:37.739 10566-10566/com.example.sampleMeibo I/System.out: 1064,America,ニューヨーク 2022-01-05 14:33:37.739 10566-10566/com.example.sampleMeibo I/System.out: 1099,China,上海 2022-01-05 14:33:37.739 10566-10566/com.example.sampleMeibo I/System.out: 0068,UK,ロンドン 2022-01-05 14:33:37.739 10566-10566/com.example.sampleMeibo I/System.out: 9999,Russia,モスクワ 2022-01-05 14:33:37.739 10566-10566/com.example.sampleMeibo I/System.out: 一致していません

該当のソースコード

package com.example.sampleMeibo; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InputStream is = null; BufferedReader br = null; String text = ""; //TextView2の処理 try { try { // assetsフォルダ内のcord.txtを開く is = this.getAssets().open("test1/cord.txt"); br = new BufferedReader(new InputStreamReader(is)); //1行単位で読み込む String str; while ((str = br.readLine()) != null) text += (str + "\n"); } finally { if (is != null) is.close(); if (br != null) br.close(); } } catch (Exception e) { //エラー発生時に前のアクティビティに戻る finish(); } //textをTextView2に表示 TextView textView2 = findViewById(R.id.textView2); textView2.setText(text); //終了ボタンを押した際の処理 Button button2 = findViewById(R.id.button2); button2.setOnClickListener(view -> finishAndRemoveTask()); //検索ボタンを押した際の処理 Button button = findViewById(R.id.button); String finalText = text; button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { //text1に保存されたコードをtextViewに表示 EditText editText = findViewById(R.id.editText); String text1 = editText.getText().toString(); TextView textView = findViewById(R.id.textView); TextView textView3 = findViewById(R.id.textView3); textView.setText(text1); System.out.println(text1); System.out.println(finalText); //コードと4桁の番号が一致したとき、該当する行を表示 if (text1 == finalText) { System.out.println("一致しました"); textView3.setText(finalText); } else { System.out.println("一致していません"); textView3.setText("一致していません"); } } }); } } //cord.txtの内容 1064,America,ニューヨーク 1099,China,上海 0068,UK,ロンドン 9999,Russia,モスクワ

試したこと

テキストファイルを読み込むのではなく、SQLiteのようなデータベースを利用したものも調べていくうちにたどり着いだのですが、まだ初心者ということもあり可能であればこのままのやり方で考えています。
しかしそもそも実現不可能なものであればほかのやり方を提示していただけると助かります。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2022/01/05 06:12 編集

まず java での文字列の比較の仕方につきまして、お調べになっては如何でしょうか。
jimbe

2022/01/05 11:10 編集

本件に SQLite が関係無いのでしたら、 SQLite のタグは外されたほうが良いと思います。 ついでに言えば、「入力した番号とテキストファイル内の番号が一致していても一致していないことになる」のは元データがテキストファイルだとか SQLite だとかは関係ありません。
Yamade

2022/01/05 12:38

ありがとうございます! Javaはequalsメソッドを使う必要があるのですね タグは修正させていただきます。
guest

回答1

0

ベストアンサー

プログラムは、データをどう扱うのかが核心です。
ですので、データをどう保持するかも重要になります。
Android の入門書等では主に画面関係に焦点が当たり易いと思いますが、それ以前として、アプリとしてのデータの扱い方を知っている・分かっている必要があります。

複数データを改行で区切って一つの String にするという扱いは、一般的では無いと思います。
配列やリスト等、複数のデータを『複数のまま』保持する構造を勉強されては如何でしょうか。


例えば以下のようなクラスを用意します。 cord ファイルの一行に当たるデータクラスです。
各フィールドは変に変更されないよう final にした上で公開します。
データの単位をクラス化することで、それぞれの意味を名前や構造から伝える/知ることが出来ます。

java

1class Cord { 2 final String code, country, city; 3 4 Cord(String code, String country, String city) { 5 this.code = code; 6 this.country = country; 7 this.city = city; 8 } 9 10 @Override 11 public String toString() { 12 return code + "," + country + "," + city; 13 } 14}

そして、 cord.txt ファイル全体に相当し、 Cord オブジェクトのリストを保持するクラスを作ります。
現状ではファイルからこのオブジェクトを生成するため、 static な create メソッドで、 BufferedReader から自身を構成するようにしています。パラメータが BufferedReader なのは、読み込み元を限定せず必要最小限にするためです。
このクラスに対して行いたい処理である、 Cord オブジェクトを探して返すメソッドや、ファイルの形式で文字列化するメソッドも用意します。

java

1class CordsData { 2 static CordsData create(BufferedReader br) throws IOException { 3 List<Cord> list = new ArrayList<>(); 4 for(String line; (line = br.readLine()) != null;) { 5 String[] tokens = line.split(","); 6 if(tokens.length != 3) throw new IOException("format error. line='"+line+"'"); 7 list.add(new Cord(tokens[0], tokens[1], tokens[2])); 8 } 9 return new CordsData(list); 10 } 11 12 private List<Cord> list; 13 CordsData(List<Cord> list) { 14 this.list = list; 15 } 16 17 Cord getCordByCode(String code) { 18 for(Cord cord : list) if(cord.code.equals(code)) return cord; 19 return null; //無かった 20 } 21 22 @Override 23 public String toString() { 24 StringJoiner sj = new StringJoiner("\n"); 25 for(Cord cord : list) sj.add(cord.toString()); 26 return sj.toString(); 27 } 28}

このクラスによって、ファイルからの読み込みは以下のように書けます。
(try-with-resources 文 を使用することで finally や close を省いています)

java

1private CordsData cordsData; //フィールドとして定義 2 3 try(InputStream is = getAssets().open("test1/cord.txt"); 4 BufferedReader br = new BufferedReader(new InputStreamReader(is));) { 5 cordsData = CordsData.create(br); 6 } catch (Exception e) { 7 e.printStackTrace(); 8 finish(); //エラー発生時に前のアクティビティに戻る 9 }

また、検索は CordData クラスのメソッドをそのまま使えます。

java

1 //一致するコードがあったら表示 2 Cord cord = cordsData.getCordByCode(text1); 3 if (cord != null) { 4 System.out.println("一致しました"); 5 textView3.setText(cord.toString()); 6 } else { 7 System.out.println("一致していません"); 8 textView3.setText("一致していません"); 9 }

投稿2022/01/05 06:29

編集2022/01/06 13:42
jimbe

総合スコア12625

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Yamade

2022/01/05 12:39

一般的ではないということは、できることはできるということでしょうか
jimbe

2022/01/05 14:54

できることはできます。 ですが、「初心者が」意地を張って経験する必要があるような方向ではありません。 回答に書きましたが、データをどのように扱うか、言い換えれば、どう扱えるか、をご理解されるのが大切と考えます。 Card.txt から各データオブジェクトを生成し、検索はそのオブジェクト群から一つを取り出して表示する…という形が一般的と私は思います。
Yamade

2022/01/08 13:23

年始で忙しく返事が遅れて申し訳ないです。 具体的なコードも含めた回答ありがとうございます! 回答していただいたことを参考にやってみたのですが CordsDataクラスのstaticという部分で、Inner classes cannot have static declations というエラー文と ファイルを読み込む際のpublic CordsData cordData;のpublicという部分で、修飾子'public'はここでは使用できませんというエラー文が出てきてしまいました。 これは回答していただいた記述外でのミスが原因になりますでしょうか。
jimbe

2022/01/08 14:07

CordsData はインナークラスでは無く単体のクラスとして書いてあります。 ですので、それぞれを MainActivity.java と同じディレクトリに Cord.javaCordsData.java として作成(それぞれに MainActivity と同じ package 文を追加)するか、 MainActivity.java 内に import ~ class Cord { ~ } class CordsData { ~ } public class MainActivity ~ と並べるか、インナークラスにするのでしたら、 static class CordsData にする必要があります。 > public CordsData cordData; という行はありません。 private CordsData cordsData; です。 この定義はその後ろにコメントを書いてあります通り、MainActivity のフィールドとして定義する必要があります。
Yamade

2022/01/09 04:43 編集

回答ありがとうございます。 失礼いたしました。エラーは発生しなくなりましたが、実際に動かしてみてもコードと入力番号が一致した際正しく動かなかったので回答していただいた部分以外を再度見直してみようと思います。
jimbe

2022/01/09 05:09

> cordsDataが初期化されていません であれば、フィールド定義した private CordsData cordsData; を private CordsData cordsData = null; としますと、一応初期化されますので消えるかと思います。
jimbe

2022/01/09 05:14

こちらではご提示のコードに回答のコードを組み合わせて動作させていますが、回答としましては個々の説明もあってあえて追加修正部分のみを書かせて頂いています。 どうしても纏まらないようでしたら全文を載せますが、(勝手な思いですが)もう少しで自力で達成されそうですので…。
Yamade

2022/01/09 06:03

ありがとうございます! そのときはまたコメントさせていただこうと思います。よろしくお願いいたします。
Yamade

2022/01/11 10:33

正しく動作させることができました! しかし以下の部分について完全に理解出来ていないので、ここについてもしよかったらどういう役割を果たしているのか教えていただけないでしょうか private List<Cord> list; CordsData(List<Cord> list) { this.list = list; } Cord getCordByCode(String code) { for(Cord cord : list) if(cord.code.equals(code)) return cord; return null; //無かった }
jimbe

2022/01/11 10:51

おめでとうございます。 private List<Cord> list; CordsData(List<Cord> list) { this.list = list; } は、コンストラクタで list を受け取って自身のフィールドに保存しています。 パラメータの list は、 create メソッドによって、ファイルから読み込んだデータが (行毎に Cord オブジェクトとして) 既に設定された状態になっています。 Cord getCordByCode(String code) { for(Cord cord : list) if(cord.code.equals(code)) return cord; return null; //無かった } は、コンストラクタで保存された list から、 code に一致するデータを持つ Cord オブジェクトを探して、有ったらそれを return しています。 for(Cord cord : list) は "拡張 for 文" と呼ばれる書き方で、ループ毎に list に含まれるオブジェクトを先頭から一つずつ cord に設定してくれます。その cord の中の code が 、メソッドのパラメータ code と一致するかを equals メソッドで判断しています。 一致するものがあればループ内から直接 return していますので、ループを終わって次の処理に進むとすればそれは該当データが無かった場合です。 ですのでその時は null を return するようにしています( "//無かった" のコメント部分)。 これにより、 getCordByCode の呼び出し側では、戻り値を受け取る変数 cord が null かどうかで "一致した"/"一致していない" と判断できることになります。
Yamade

2022/01/15 16:58

細かい解説までありがとうございました。また機会があればよろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問