在Android Studio Java中从文本文件中读取

9

我有一个名为QuoteBank的类,需要使用Scanner读取一个txt文件,但是它出现了文件未找到的异常。

java文件位于app/src/main/java/nate.marxBros/QuoteBank.java

txt文件位于app/src/main/assets/Quotes.txt

代码如下:

File file = new File("assets/QuotesMonkeyBusiness.txt");
    Scanner input = null;
    try {
        input = new Scanner(file);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

这个程序不应该和其他Java程序一样工作吗?但它给出了文件未找到的异常。

我在这个网站上尝试了很多方法,例如Android Studio从原始资源文本文件中读取,但是这种方法不起作用,因为我不知道如何传递Context。

感谢任何帮助。

更新后的代码:

public class QuoteBank {
private ArrayList<ArrayList<QuoteBank>> bank;
private Context mContext;
private ArrayList<QuoteQuestion> monkeyBuisness;


public QuoteBank(Context context){
    mContext = context;
    InputStream is = null;
    try {
        is = mContext.getAssets().open("QuotesMonkeyBusiness.txt");
    } catch (IOException e) {
        e.printStackTrace();
    }

    ArrayList<QuoteQuestion> monkeyBuisness = parseFileToBank(is);
}

主活动

public class MainActivity extends ActionBarActivity {
QuoteBank b = new QuoteBank(MainActivity.this);
3个回答

12

你应该拥有一个MainActivity.java或一些Activity,它会实例化QuoteBank。您需要使构造函数接受上下文参数:

QuoteBank.java中设置一个私有变量:

private Context mContext;

设置构造函数:

public QuoteBank(Context context) {
   this.mContext = context;
}

然后在您的活动中实例化它,

QuoteBank quoteBank = new QuoteBank(context);

在活动中,可以通过thisActivity.this指令调用上下文变量,其中将“Activity”替换为您的活动名称。或者,如果您在片段中,则可以通过onCreateView(...)方法中的View对象获取上下文。通常是通过调用view.getContext()来完成的。

现在,在您获取资产的方法中,您可以使用上下文:

InputStream is = mContext.getAssets().open("QuotesMonkeyBusiness.txt")

如果您正在使用Android Studio,您可以创建一个main(String[] args) { ... }方法并运行它,或者只需启动模拟器并让它使用Log.d(...)来显示文件输出。

或者,您也可以使用以下方法:

AssetManager am = mContext.getAssets();
InputStream is = am.open("QuotesMonkeyBusiness.txt");

也许将QuoteBank作为单例实例会更加高效,但这完全取决于你的需求,可能会是这样:

List<String> allTextLines = QuoteBank.readFromFile(context, path_to_file);

然后在您的QuoteBank.java类中,您可以编写如下的方法:

/**
* Created by AndyRoid on 5/23/15.
*/
public class QuoteBank {

private Context mContext;

public QuoteBank(Context context) {
    this.mContext = context;
}

public List<String> readLine(String path) {
    List<String> mLines = new ArrayList<>();

    AssetManager am = mContext.getAssets();

    try {
        InputStream is = am.open(path);
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        String line;

        while ((line = reader.readLine()) != null)
            mLines.add(line);
    } catch (IOException e) {
        e.printStackTrace();
    }

    return mLines;
}

}

然后在我的MainActivity.java类中,我有以下代码:

/**
 * Created by AndyRoid on 5/23/15.
 */
public class MainActivity extends AppCompatActivity {

public static final String TAG = MainActivity.class.getSimpleName();

public static final String mPath = "adventur.txt";
private QuoteBank mQuoteBank;
private List<String> mLines;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mQuoteBank = new QuoteBank(this);
    mLines = mQuoteBank.readLine(mPath);
    for (String string : mLines)
        Log.d(TAG, string);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

这是我的项目结构:

enter image description here

这是我从一个随机数据库下载的adventur.txt文件:

file

这是我的日志输出:

enter image description here


更新: 为什么你不应该在Android中使用Scanner

来自官方文档:

http://developer.android.com/reference/java/util/Scanner.html

这个类并没有想象中那么有用。它在机器之间通信时很低效;你应该使用 JSON、protobufs,甚至 XML 进行通信。非常简单的用途可能可以使用 split(String) 方法实现。对于来自人类的输入,使用区域设置特定的正则表达式不仅代价高昂,而且也有些难以预测。

Scanner 类不是线程安全的。


最后说明:

我强烈建议您阅读这里使用的所有对象的文档,以便您理解整个过程。


感谢关于构造函数的部分帮助。但是我仍然在 AssetManager am = mContext.getAssets(); 这一行遇到了空指针异常。在主活动中,我已经声明了上下文变量,如 Activity context = new Activity(); 并且在那一行之前,我已经将 this.mContext = context; 赋值了。 - Tintinabulator Zea
有没有办法只通过输入相对文件路径到文件类中来完成它?我觉得那样会更容易一些。我不确定InputStream是否能与Scanner.nextLine()方法一起使用。 - Tintinabulator Zea
不要使用 Activity context = new Activity(); 来获取上下文,而是使用命令 thisYOURACTIVITYNAME.this。因此,它应该像这样:QuoteBank qb = new QuoteBank(this); 或 **QuoteBank qb = new QuoteBank(YOURACTIVITYNAME.this);**(假设您没有选择单例路线)。 - AndyRoid
好的,我已经更新了我的代码,但是它仍然在'is = mContext.getAssets().open("QuotesMonkeyBusiness.txt");'处给出空指针异常。错误信息显示在android.content.ContextWrapper.getAssets(ContextWrapper.java:83)。 - Tintinabulator Zea
我已经在我的安卓设备上成功运行了它,我会更新代码。 - AndyRoid
出于好奇,那个冒险是游戏还是什么?它实际上是什么? - Spikatrix

3
简单问题的简单回答。
private String readFile()
{
    String myData = "";
    File myExternalFile = new File("assets/","log.txt");
    try {
        FileInputStream fis = new FileInputStream(myExternalFile);
        DataInputStream in = new DataInputStream(fis);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        String strLine;
        while ((strLine = br.readLine()) != null) {
            myData = myData + strLine + "\n";
        }
        br.close();
        in.close();
        fis.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return myData;
}

只需使用函数来读取外部文件。


1

Context.getResources().getAssets().open("QuotesMonkeyBusiness.txt"); 返回一个 InputStream,剩下的你可以自己处理。

编辑

因为我不知道如何传递 Context

其实,Context 随处可见,如果你有一个 View,你可以获取到 Context,如果你有一个 Activity,你也可以获取到 Context,所以找到它吧。

希望能对你有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接