エラーメッセージを理解するのに助けが必要です
-
09-12-2019 - |
質問
以下は、プログラムで結果を表示しようとすると表示され続けるエラー メッセージです。
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at AddressBookIO.getEntriesString(AddressBookIO.java:38)
at AddressBookEntryApp.main(AddressBookEntryApp.java:42)
私のコードは正しいとほぼ確信しています。私のプログラムは、結果を表示することを除いて、想定されているすべてのことを実行します。「メイン」java.lang.ArrayIndexOutOfBoundsException:0」は私を混乱させる部分です。
AddressBookIO.java と AddressBookEntryApp のコードは次のとおりです。
import java.io.*;
public class AddressBookIO
{
private static File addressBookFile = new File("address_book.txt");
private static final String FIELD_SEP = "\t";
private static final int COL_WIDTH = 20;
// use this method to return a string that displays
// all entries in the address_book.txt file
public static String getEntriesString()
{
BufferedReader in = null;
try
{
checkFile();
in = new BufferedReader(
new FileReader(addressBookFile));
// define the string and set a header
String entriesString = "";
entriesString = padWithSpaces("Name", COL_WIDTH)
+ padWithSpaces("Email", COL_WIDTH)
+ padWithSpaces("Phone", COL_WIDTH)
+ "\n";
entriesString += padWithSpaces("------------------", COL_WIDTH)
+ padWithSpaces("------------------", COL_WIDTH)
+ padWithSpaces("------------------", COL_WIDTH)
+ "\n";
// append each line in the file to the entriesString
String line = in.readLine();
while(line != null)
{
String[] columns = line.split(FIELD_SEP);
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
entriesString +=
padWithSpaces(name, COL_WIDTH) +
padWithSpaces(emailAddress, COL_WIDTH) +
padWithSpaces(phoneNumber, COL_WIDTH) +
"\n";
line = in.readLine();
}
return entriesString;
}
catch(IOException ioe)
{
ioe.printStackTrace();
return null;
}
finally
{
close(in);
}
}
// use this method to append an address book entry
// to the end of the address_book.txt file
public static boolean saveEntry(AddressBookEntry entry)
{
PrintWriter out = null;
try
{
checkFile();
// open output stream for appending
out = new PrintWriter(
new BufferedWriter(
new FileWriter(addressBookFile, true)));
// write all entry to the end of the file
out.print(entry.getName() + FIELD_SEP);
out.print(entry.getEmailAddress() + FIELD_SEP);
out.print(entry.getPhoneNumber() + FIELD_SEP);
out.println();
}
catch(IOException ioe)
{
ioe.printStackTrace();
return false;
}
finally
{
close(out);
}
return true;
}
// a private method that creates a blank file if the file doesn't already exist
private static void checkFile() throws IOException
{
// if the file doesn't exist, create it
if (!addressBookFile.exists())
addressBookFile.createNewFile();
}
// a private method that closes the I/O stream
private static void close(Closeable stream)
{
try
{
if (stream != null)
stream.close();
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
// a private method that is used to set the width of a column
private static String padWithSpaces(String s, int length)
{
if (s.length() < length)
{
StringBuilder sb = new StringBuilder(s);
while(sb.length() < length)
{
sb.append(" ");
}
return sb.toString();
}
else
{
return s.substring(0, length);
}
}
}
そして
import java.util.Scanner;
public class AddressBookEntryApp
{
public static void main(String args[])
{
// display a welcome message
System.out.println("Welcome to the Address Book application");
System.out.println();
Scanner sc = new Scanner(System.in);
int menuNumber = 0;
while (menuNumber != 3)
{
// display menu
System.out.println("1 - List entries");
System.out.println("2 - Add entry");
System.out.println("3 - Exit\n");
// get input from user
menuNumber = Validator.getIntWithinRange(sc, "Enter menu number: ", 0, 4);
System.out.println();
switch (menuNumber)
{
case 1:
{
String entriesString = AddressBookIO.getEntriesString();
System.out.println(entriesString);
break;
}
case 2:
{
// get data from user
String name = Validator.getRequiredString(sc, "Enter name: ");
String emailAddress = Validator.getRequiredString(sc, "Enter email address: ");
String phoneNumber = Validator.getRequiredString(sc, "Enter phone number: ");
// create AddressBookEntry object and fill with data
AddressBookEntry entry = new AddressBookEntry();
entry.setName(name);
entry.setEmailAddress(emailAddress);
entry.setPhoneNumber(phoneNumber);
AddressBookIO.saveEntry(entry);
System.out.println();
System.out.println("This entry has been saved.\n");
break;
}
case 3:
{
System.out.println("Goodbye.\n");
break;
}
}
}
}
}
解決
ArrayIndexOutOfBoundsException
指定された配列のサイズを超えるインデックスにアクセスしようとすると、スローされます。
これを変更してみてください:
while(line != null)
{
String[] columns = line.split(FIELD_SEP);
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
entriesString += padWithSpaces(name, COL_WIDTH) +
padWithSpaces(emailAddress, COL_WIDTH) +
padWithSpaces(phoneNumber, COL_WIDTH) +
"\n";
line = in.readLine();
}
これに:
while(line != null)
{
String[] columns = line.split(FIELD_SEP);
if (columns.length > 2)
{
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
entriesString += padWithSpaces(name, COL_WIDTH) +
padWithSpaces(emailAddress, COL_WIDTH) +
padWithSpaces(phoneNumber, COL_WIDTH) +
"\n";
}
line = in.readLine();
}
他のヒント
例外は、配列のサイズを超えて配列の要素にアクセスしていることを意味します。だから、あなたはあなたが問題の原因を知らせることができるようにあなたのコードの詳細を提供する必要があります。
アレイが不正なインデックスでアクセスされたことを示します。インデックスは、アレイのサイズと負またはそれ以上のサイズ以上です。
あなたのエラーログに従って.. AddressBookIO.java
の1行目の番号:38はこの例外を投げています。
ここにいることができます..
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
.
0,1または2のいずれかに要素がない場合。
エラーメッセージはかなり明確である:要素を持つ配列の1次要素(インデックス0)が誤ってアクセスされています。
スレッドの例外「MAIN」 java.lang.ArrayIndexOutOfBoundSexception:[Index Is] 0
例えば、この例外をスローします。
.int bad = (new int[0])[0]; // no elements :(
次のことは問題ありません:
.int ok = (new int[1])[0]; // one element, can access it!
私はそれがこれであると思う:
.String[] columns = line.split(FIELD_SEP); // empty array? String name = columns[0]; // KABOOM!
例外の行 のコードを確認してください。
at addressbook.getentriesstring( addressbookio.java:38 )
'address_book.txt'の空白行?
空の配列の最初の要素にアクセスしようとしています。存在しないので、実行時から例外が表示されます。
アクセスしようとしている配列は、split()
メソッドの結果です。これは、区切り文字の文字列を渡す場合にのみ空の配列を返します."\t"
だから、それらの間では何もないタブのみを含むいくつかの行がなければなりません。
split()
を使用する代わりに、各行に正規表現を適用することを検討してください。このようにして、空の文字列であっても、各フィールドの値を簡単に抽出するために、行とのフォーマットを同時に検証できます。
.Pattern p = Pattern.compile("([^\t]*)\t([^\t]*)\t([^\t]*)");
...
Matcher m = p.matcher(line);
if (!m.matches()) {
/* The line is invalid; skip it or throw an exception. */
...
}
String name = m.group(1);
String emailAddress = m.group(2);
String phoneNumber = m.group(3);