Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Application Has Too Many Files Open - Android

I have a method called calcDays() which loops through a database over and over again until a certain condition is met. The problem is that Android studio is telling me that I've run out of files. I realize that I'm opening databases and not closing them, which is why I have the error. However, I cannot seem to fix this error.

Class with calcDays() method

    package com.example.brandon.netflixcalculator;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException;
import java.util.Calendar;

public class MainActivity extends Activity {

    private Button b1;
    private Button b2;
    private Button b3;
    private Button b4;
    private TextView daysRemaining, showName;;
    private int x;
    private int[] dailyMin = new int[7];
    private String[] dailyPercent = {"100%", "75%", "50%", "25%", "0%"};
    private double[] percent = {1, .75, .5, .25, 0};
    private DatabaseHelper db;
    String[] stringDays = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
    private File viewingInfo;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setOnButton1ClickListener();
        setOnButton2ClickListener();
        setOnButton3ClickListener();
        setOnButton4ClickListener();
        daysRemaining = (TextView)findViewById(R.id.textViewRemainingDays);
        showName = (TextView)findViewById(R.id.textViewCurrentShow);
        if(!ifFileExists()){
            createDBFirstTime();
        }
        else{
            db = new DatabaseHelper(getApplicationContext());
            daysRemaining.setText(String.valueOf(calcDays()));
            showName.setText(db.getShowName());
        }
    }

    public void createDBFirstTime(){
        System.out.println("Database deleted? " + this.deleteDatabase("viewing_database"));
        db = new DatabaseHelper(this.getApplicationContext());
        for(int i = 0; i < stringDays.length; i++){
            db.insertDataViewing(stringDays[i], 0, "100%");
        }
        db.insertDataShow("N/A", 0, 0, 0);
        try {
            FileOutputStream fos = openFileOutput("madeDB", MODE_PRIVATE);
            try {
                fos.write("true".getBytes());
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }


    public boolean ifFileExists(){
        File file = getApplicationContext().getFileStreamPath("madeDB");
        if(file.exists())
            return true;
        else return false;
    }


    public int calcDays() {
        int seasons, episodes, epiLength;
        int[] info = new int[3];
        for(int i = 0; i < info.length; i++){
            info[i] = db.extractShowInfo()[i];
        }
        seasons = info[0];
        episodes = info[1];
        epiLength = info[2];
        int totalTime = (seasons * episodes * epiLength);
        System.out.println(seasons);
        int dayOfWeek = getDay();
        int days = 0;
        int y;
        double z;
        while (totalTime > 0) {
            y = db.getMin(dayOfWeek);
            z = db.getPercentage(dayOfWeek);
            totalTime -= y*z;
            dayOfWeek++;
            if (dayOfWeek == 7) {
                dayOfWeek = 0;
            }
            days++;
        }

        return days;
    }

    public int getDay() {
        Calendar calendar = Calendar.getInstance();
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        return day;
    }


    public void setOnButton1ClickListener() {
        b1 = (Button) findViewById(R.id.button);
        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent("com.example.brandon.netflixcalculator.RoughGuessActivity");
                startActivity(i);
            }
        });
    }

    public void setOnButton2ClickListener() {
        b2 = (Button) findViewById(R.id.button2);
        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent("com.example.brandon.netflixcalculator.Exact_Activity");
                startActivity(i);
            }
        });
    }

    public void setOnButton3ClickListener() {
        b3 = (Button) findViewById(R.id.button3);
        b3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent i = new Intent("com.example.brandon.netflixcalculator.ShowInfoActivity");
                startActivity(i);
            }
        });
    }

    public void setOnButton4ClickListener() {
        b4 = (Button) findViewById(R.id.btnUpdate);
        b4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                System.out.println("-----------------------------------------------------");
                System.out.println(calcDays());
                showMessage("Days remaining", String.valueOf(calcDays()));
                daysRemaining.setText(String.valueOf(calcDays()));
            }

        });

    }

    public int getTotalMin(){
        int x = 0;
        Cursor res = db.getWritableDatabase().rawQuery("select MINUTES from VIEWING", null);
        StringBuffer sb = new StringBuffer();
        while(res.moveToNext()){
            x += Integer.parseInt(res.getString(0));
        }
        return x;
    }


    public void readDB(){
        Cursor res = db.getAllData("SHOW_INFO");
        if (res.getCount() == 0) {
            showMessage("Error", "No data found");
            return;
        }
        StringBuffer sb = new StringBuffer();
        while (res.moveToNext()) {
            sb.append("\nName: " + res.getString(1) + "\nSeasons: "
                    + res.getString(2) + "\nEpisodes: " + res.getString(3) + "\nEpisode Length: " +
                    res.getString(4));
        }
        showMessage("Test", sb.toString());
        db.close();

    }

    public void showMessage(String title, String msg){
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setCancelable(true);
        builder.setTitle(title);
        builder.setMessage(msg);
        builder.show();
    }
}

DatabaseHelper Class

public class DatabaseHelper extends SQLiteOpenHelper{

    private static final String dbName = "viewing_database";
    private static final String tableViewing = "VIEWING";
    private static final String tableShowInfo = "SHOW_INFO";
    private static final String COL_1 = "ID";
    private static final String COL_2 = "WEEKDAY";
    private static final String COL_3 = "MINUTES";
    private static final String COL_4 = "PERCENTAGE";
    private static DatabaseHelper sInstance;


    public DatabaseHelper(Context context) {
        super(context, dbName, null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
       db.execSQL("create table " + tableViewing + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, WEEKDAY TEXT, MINUTES INTEGER, PERCENTAGE TEXT)");
       db.execSQL("create table " + tableShowInfo + " (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT, SEASONS INTEGER, EPISODES INTEGER," +
               " EPISODE_LENGTH INTEGER)");
    }

    public static synchronized DatabaseHelper getInstance(Context context) {
        // Use the application context, which will ensure that you
        // don't accidentally leak an Activity's context.
        if (sInstance == null) {
            sInstance = new DatabaseHelper(context.getApplicationContext());
        }
        return sInstance;
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + tableViewing);
        db.execSQL("DROP TABLE IF EXISTS " + tableShowInfo);
        onCreate(db);
    }


    public boolean updateDataViewing(String id, String weekday, int minutes, String percentage){
        SQLiteDatabase myDataBase = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(COL_1, id);
        cv.put(COL_2, weekday);
        cv.put(COL_3, minutes);
        cv.put(COL_4, percentage);
        myDataBase.update(tableViewing, cv, "ID = ?", new String[]{id});
        myDataBase.close();
        return true;
    }

    public boolean updateDataShow(String id, String name, int seasons, int episodes, int episodeLength){
        SQLiteDatabase myDataBase = this.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(COL_1, id);
        cv.put("NAME", name);
        cv.put("SEASONS", seasons);
        cv.put("EPISODES", episodes);
        cv.put("EPISODE_LENGTH", episodeLength);
        myDataBase.update(tableShowInfo, cv, "ID = ?", new String[]{id});
        return true;
    }

    public double getPercentage(int id){
        SQLiteDatabase myDataBase = this.getWritableDatabase();
        Cursor res = myDataBase.rawQuery("select PERCENTAGE from " + tableViewing + " where ID =" + id, null);
        if (res.getCount() == 0) {
            return 0;
        }
        StringBuffer sb = new StringBuffer();
        while (res.moveToNext()) {
            sb.append(res.getString(0));
        }

        String msg = sb.toString();
        myDataBase.close();
        return Integer.parseInt(msg.substring(0, msg.length()-1)) / 100.0;
    }


    public int getMin(int id){
        SQLiteDatabase myDataBase = this.getWritableDatabase();
        Cursor res = myDataBase.rawQuery("select MINUTES from " + tableViewing + " where ID =" + id, null);
        if (res.getCount() == 0) {
            return 0;
        }
        StringBuffer sb = new StringBuffer();
        while (res.moveToNext()) {
            sb.append(res.getString(0));
        }
        myDataBase.close();
        return Integer.parseInt(sb.toString());
    }

    public Cursor getAllData(String tableName){
        SQLiteDatabase myDataBase = this.getWritableDatabase();
        Cursor res = myDataBase.rawQuery("select * from " + tableName, null);
        return res;
    }

    public boolean insertDataViewing(String dayOfWeek, int minutes, String percentage){
        SQLiteDatabase myDataBase = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put(COL_2, dayOfWeek);
        cv.put(COL_3, minutes);
        cv.put(COL_4, percentage);
        double result = myDataBase.insert(tableViewing, null, cv);
        myDataBase.close();
        return(result != -1);
    }

    public boolean insertDataShow(String name, int seasons, int episodes, int episodeLength){
        SQLiteDatabase myDataBase = getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("NAME", name);
        cv.put("SEASONS", seasons);
        cv.put("EPISODES", episodes);
        cv.put("EPISODE_LENGTH", episodeLength);
        double result = myDataBase.insert(tableShowInfo, null, cv);
        myDataBase.close();
        return(result != -1);
    }

    public String getShowName(){
        Cursor res = getAllData("SHOW_INFO");
        if (res.getCount() == 0) {
            System.out.println("No data found");
            return "N/A";
        }
        StringBuffer sb = new StringBuffer();
        while (res.moveToNext()) {
            sb.append(res.getString(1));
        }
        return sb.toString();
    }

    public int[] extractShowInfo() {
        int[] info = new int[3];
        Cursor res = getAllData("SHOW_INFO");
        if (res.getCount() == 0) {
            System.out.println("No data found");
            return new int[] {0, 0, 0};
        }
        while(res.moveToNext()){
            info[0] = Integer.parseInt(res.getString(2)); //seasons
            info[1] = Integer.parseInt(res.getString(3)); //episodes
            info[2] = Integer.parseInt(res.getString(4)); //episode length
        }

        for(int x:info){
            System.out.println(x);
        }

        return info;

    }

}

And finally the error

04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator W/SQLiteLog: (28) failed to open "/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal" with flag (131072) and mode_t (1b0) due to error (24)
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) cannot open file at line 31517 of [2ef4f3a5b1]
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) os_unix.c:31517: (24) open(/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal) - 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator W/SQLiteLog: (28) failed to open "/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal" with flag (131074) and mode_t (1b0) due to error (24)
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator W/SQLiteLog: (28) failed to open "/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal" with flag (131072) and mode_t (1b0) due to error (24)
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) cannot open file at line 31517 of [2ef4f3a5b1]
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (14) os_unix.c:31517: (24) open(/data/user/0/com.example.brandon.netflixcalculator/databases/viewing_database-journal) - 
04-06 13:59:22.081 1327-1327/com.example.brandon.netflixcalculator E/SQLiteLog: (2062) statement aborts at 9: [select PERCENTAGE from VIEWING where ID =4] unable to open database file
04-06 13:59:22.091 1327-1327/com.example.brandon.netflixcalculator E/SQLiteQuery: exception: unable to open database file (code 2062)
                                                                                  #################################################################
                                                                                  Error Code : 2062 (SQLITE_CANTOPEN_EMFILE)
                                                                                  Caused By : Application has opened two many files. Maximum of available file descriptors in one process is 1024 in default.
                                                                                    (unable to open database file (code 2062))
                                                                                  #################################################################; query: select PERCENTAGE from VIEWING where ID =4
04-06 13:59:22.091 1327-1327/com.example.brandon.netflixcalculator D/AndroidRuntime: Shutting down VM
04-06 13:59:22.091 1327-1327/com.example.brandon.netflixcalculator E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                     Process: com.example.brandon.netflixcalculator, PID: 1327
                                                                                     android.database.sqlite.SQLiteCantOpenDatabaseException: unable to open database file (code 2062)
                                                                                     #################################################################
                                                                                     Error Code : 2062 (SQLITE_CANTOPEN_EMFILE)
                                                                                     Caused By : Application has opened two many files. Maximum of available file descriptors in one process is 1024 in default.
                                                                                        (unable to open database file (code 2062))
                                                                                     #################################################################
                                                                                         at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
                                                                                         at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:980)
                                                                                         at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
                                                                                         at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
                                                                                         at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
                                                                                         at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
                                                                                         at com.example.brandon.netflixcalculator.DatabaseHelper.getPercentage(DatabaseHelper.java:83)
                                                                                         at com.example.brandon.netflixcalculator.MainActivity.calcDays(MainActivity.java:108)
                                                                                         at com.example.brandon.netflixcalculator.MainActivity$4.onClick(MainActivity.java:166)
                                                                                         at android.view.View.performClick(View.java:5697)
                                                                                         at android.widget.TextView.performClick(TextView.java:10815)
                                                                                         at android.view.View$PerformClick.run(View.java:22526)
                                                                                         at android.os.Handler.handleCallback(Handler.java:739)
                                                                                         at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                         at android.os.Looper.loop(Looper.java:158)
                                                                                         at android.app.ActivityThread.main(ActivityThread.java:7229)
                                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
                                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
04-06 13:59:28.401 1327-1338/com.example.brandon.netflixcalculator W/SQLiteConnectionPool: A SQLiteConnection object for database '+data+user+0+com_example_brandon_netflixcalculator+databases+viewing_database' was leaked!  Please fix your application to end transactions in progress properly and to close the database when it is no longer needed.
04-06 14:04:22.231 1327-1327/com.example.brandon.netflixcalculator I/Process: Sending signal. PID: 1327 SIG: 9
like image 771
Brandon Loehle Avatar asked Apr 06 '16 18:04

Brandon Loehle


People also ask

Could not accept connection java io IOException too many open files?

The error Java IOException “Too many open files” can happen on high-load servers and it means that a process has opened too many files (file descriptors) and cannot open new ones. In Linux, the maximum open file limits are set by default for each process or user and the defaut values are quite small.


1 Answers

You should be creating only a single SqliteOpenHelper object for your entire app, and use that wherever database access is required. This will prevent a lot of problems with concurrent access to the database.

like image 67
Doug Stevenson Avatar answered Sep 17 '22 14:09

Doug Stevenson