ENOENT (No such file or directory) - 当文件存在于 Android Java

问题描述

一段时间后尝试 Android 开发,我试图从 FTP 下载一个 zip 文件,但即使在重复尝试后,当我尝试在 FileOutputStream 中写入文件时仍然出现 FileNotFound 异常。该文件显然存在于本地存储中,因为我打印了 2-3 次(请检查输出日志)

MainActivity.java

package com.example.myapplication;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import org.apache.commons.net.ftp.FTPFile;

import java.io.File;

public class MainActivity extends AppCompatActivity {

    private static final String LOG_TAG = "";
    Spinner drop;
    Button btn;
    String[] items;
    FTPFile[] file;
    ArrayAdapter adapter;
    ProgressDialog mProgressDialog;
    String dwnFile = "";
    String localFilePath;
    File localFile;
    FTPOps ftp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.button1);
        drop = (Spinner) findViewById(R.id.spinner);
        items = new String[]{"hello"};


        String path = Environment.getExternalStorageDirectory().toString();
        System.out.println("Path: " + path);
        File directory = new File(path);
        File[] files = directory.listFiles();

        for (int i = 0; i < files.length; i++) {
            System.out.println(files[i].getName());
        }

        items = new String[]{"Select the file","01.zip","04.zip","05.zip","06.zip","07.zip","08.zip","09.zip",};

        adapter = new ArrayAdapter(this,android.R.layout.simple_spinner_dropdown_item,items);

        drop.setAdapter(adapter);

        btn.setonClickListener(v -> {
            dwnFile = drop.getSelectedItem().toString().equals("Select the file") ? "" : drop.getSelectedItem().toString();

            if (dwnFile != "") {
                Context context = this;
                localFilePath = Environment.getExternalStorageDirectory() + "/" + "ebooks";

                localFile = new File(localFilePath + "/" + dwnFile);
                System.out.println(localFile.mkdir() ? "File created" : "Not created file");
                if (localFile.exists()) {

                    System.out.println("File created");
                } else {
                    System.out.println("File edxists already");
                }
                System.out.println(localFile.getPath());
                Toast toast = Toast.makeText(getApplicationContext(),"Downloading...",Toast.LENGTH_LONG);
                toast.show();

                ftp = new FTPOps(localFile,context,dwnFile);
                String msg = (ftp.runDownloadAndUnziping()) ? "Downloaded" : "Error in downloding";
                toast = Toast.makeText(getApplicationContext(),msg,Toast.LENGTH_LONG);
                toast.show();


            }
        });
    }
}

Mainactivity 提供一个下拉菜单,可从文件列表中进行选择,并将数据发送到另一个类以供 FTP 下载。

FTPOps.java

package com.example.myapplication;

import android.content.Context;
import android.widget.Toast;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FTPOps {
File localFile;
Context context;
FTPClient ftp;
String fileName;

public FTPOps(File localFile,Context context,String dwnFile) {
    this.localFile = localFile;
    this.context = context;
    ftp = new FTPClient();
    this.fileName = dwnFile;
}

public boolean runDownloadAndUnziping() {

    setUpFTP();


    return true;
}

private void setUpFTP() {

    Thread t = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                ftp.connect("some$$$$url");
                ftp.login("someID","somePassword");
                showToast("Login into FTP Successful");
                ftp.enterLocalPassiveMode();
                ftp.setFileType(FTP.BINARY_FILE_TYPE);

                System.out.println("Downlaod in progress for " + fileName);
                System.out.println("Local file is " + localFile.getPath());
                FileOutputStream fo = new FileOutputStream(localFile.getPath());

                if (fo == null) {
                    System.out.println("fo is null");
                }


                boolean r = ftp.retrieveFile(fileName,fo);


                if (r) {
                    System.out.println("Operation success");

                }
                fo.close();
            } catch (IOException e) {
                e.printstacktrace();
                showToast("Login Failed");
            }

        }

        private void showToast(String msg) {
            System.out.println(msg);
        }

    });

    t.start();
}

}

我的输出日志:

06/13 01:13:00: Launching 'app' on Nexus 6 API 30.
Install successfully finished in 1 s 683 ms.
$ adb shell am start -n "com.example.myapplication/com.example.myapplication.MainActivity" -a android.intent.action.MAIN -c android.intent.category.LAUNCHER
Connected to process 13263 on device 'emulator-5554'.
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
D/NetworkSecurityConfig: No Network Security Config specified,using platform default
D/NetworkSecurityConfig: No Network Security Config specified,using platform default
D/libEGL: loaded /vendor/lib/egl/libEGL_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv1_CM_emulation.so
D/libEGL: loaded /vendor/lib/egl/libGLESv2_emulation.so
W/e.myapplicatio: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist,reflection,allowed)
W/e.myapplicatio: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist,allowed)
I/System.out: Path: /storage/emulated/0
I/System.out: Android
    Music
    podcasts
    ringtones
    Alarms
    Notifications
    Pictures
    Movies
I/System.out: Download
    DCIM
    Audiobooks
    Documents
D/HostConnection: HostConnection::get() New Host Connection established 0xf24e9f30,tid 13290
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_async_frame_commands ANDROID_EMU_gles_max_version_2 
W/Openglrenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED,retrying without...
D/EGL_emulation: eglCreateContext: 0xf24ead30: maj 2 min 0 rcv 2
D/EGL_emulation: eglMakeCurrent: 0xf24ead30: ver 2 0 (tinfo 0xf28370f0) (first time)
I/Gralloc4: mapper 4.x is not supported
D/HostConnection: createUnique: call
D/HostConnection: HostConnection::get() New Host Connection established 0xf24ea390,tid 13290
D/goldfish-address-space: allocate: Ask for block of size 0x100
D/goldfish-address-space: allocate: ioctl allocate returned offset 0x3f9d95000 size 0x2000
D/HostConnection: HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_ignored_handles ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_host_side_tracing ANDROID_EMU_async_frame_commands ANDROID_EMU_gles_max_version_2 
I/Choreographer: Skipped 40 frames!  The application may be doing too much work on its main thread.
I/Openglrenderer: Davey! duration=760ms; Flags=0,IntendedVsync=24852661746550,Vsync=24853328413190,OldestInputEvent=9223372036854775807,NewestInputEvent=0,HandleInputStart=24853340948720,AnimationStart=24853340988320,PerformTraversalsstart=24853341581320,DrawStart=24853343717920,SyncQueued=24853344351620,SyncStart=24853344908520,IssueDrawCommandsstart=24853345141720,SwapBuffers=24853352646720,FrameCompleted=24853423084920,DequeueBufferDuration=981700,QueueBufferDuration=1455800,GpuCompleted=0,W/e.myapplicatio: Accessing hidden field Landroid/widget/AbsListView;->mIsChildViewEnabled:Z (greylist,allowed)
D/Openglrenderer: endAllActiveAnimators on 0xec08c3d0 (dropdownlistview) with handle 0xc3041870
I/System.out: Not created file
I/System.out: File edxists already
I/System.out: /storage/emulated/0/ebooks/06.zip
D/CompatibilityChangeReporter: Compat change id reported: 147798919; UID 10155; state: ENABLED
I/System.out: Login into FTP Successful
I/System.out: Downlaod in progress for 06.zip
***I/System.out: Local file is /storage/emulated/0/ebooks/06.ziP***
**W/System.err: java.io.FileNotFoundException: /storage/emulated/0/ebooks/06.zip: open Failed: ENOENT (No such file or directory)**
        at libcore.io.IoBridge.open(IoBridge.java:492)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:125)
        at com.example.myapplication.FTPOps$1.run(FTPOps.java:50)
        at java.lang.Thread.run(Thread.java:923)
    Caused by: android.system.ErrnoException: open Failed: ENOENT (No such file or directory)
        at libcore.io.Linux.open(Native Method)
W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7542)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:478)
        ... 4 more
I/System.out: Login Failed

我记得之前下载曾经是这样工作的,但我阅读了一些关于存储访问问题的帖子,所以我适当地更新了我的清单:

   <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.MyApplication"
    android:requestLegacyExternalStorage="true">

但结果是一样的。

现在我需要帮助理解:

  • 为什么文件存在时会出现 FileNotFoundException 异常,因为它会在崩溃前显示在屏幕上
  • 即使我记得之前使用过的 Toast 在 MainActivity.java 中也根本无法使用
  • 我还需要解压缩下载的文件,如果有人对新库有更好的建议,或者它仍然以旧方式工作?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)