精华内容
下载资源
问答
  • File类(操作目录文件)构造方法:Filefile=new File("adfsdg\D:\\java.txt");(可以构造个抽象的目录不确定存不存在!); File a=newFilefile1,"java.txt"); File file1=newFile(a,&...

    File类(操作目录文件)

    构造方法:Filefile=new File("adfsdg\D:\\java.txt");(可以构造一个抽象的目录不确定存不存在!);

       File a=newFile(file1,"java.txt"); 

       File file1=newFile(a,"java.txt"); 两种构造方法;

    成员方法:

    public class DemoC {
    
    public staticvoid main(String[] args) {
    
    Filefile2=new File("demo.txt");
    
    String a=file2.getAbsolutePath();//获取绝对路径
    
    System.out.println(a);
    
    String b=file2.getName();//获取文件或者目录的名称
    
    System.out.println(b);
    
    String c=file2.getPath();//取到的是构造时候的路径
    
    System.out.println(c);
    
    long d=file2.length();//文件大小byte
    
    System.out.println(d);
    
    }
    
    }

    下面是File类的成员方法
    文件和文件夹的创建删除等
    	public class DemoC {
    public static void main(String[] args) throws IOException {
    	File file2=new File("demo.txt");
    
    	//创建文件
    	System.out.println("创建文件:"+file2.createNewFile());
    	
    	//创建单级目录
    	File file3=new File("demo");
    	System.out.println("创建单级目录:"+file3.mkdir());
    
    	//创建多级目录
    	File file4=new File("demo\\demo\\demo");
    	System.out.println("创建多级目录:"+file4.mkdirs());
    
    	//删除单文件或者空目录
    	File file5=new File("demo.txt");
    	System.out.println("删除文件或者空目录"+file5.delete());
    	
    	//判断目录或者文件存不存在
    	File file6=new File("demo.txt");
    	System.out.println("判断目录或者文件存不存在"+file6.exists());
    	
    	//判断是否是目录
    	File file7=new File("demo.txt");
    	System.out.println("判断是否是目录"+file7.isDirectory());
    
    	//判断是否是文件
    	File file8=new File("demo.txt");
    	System.out.println("判断是否是文件"+file8.isFile());
    	
    	//获取当前文件子文件、子目录的数组
    	File [] file=file4.listRoots();
    	for (File f : file) {
    		System.out.println(f.isFile()?"文件":"目录"+f);
    	
    	
    	//获取所有目录
    	File []arr = file8.listFile();
    
    	//File的listFile()方法返回null的几种情况!
    	//当File代表的是一个文件的时候!
    	//当File代表一个系统文件目录的时候!
    	//当File代表的文件或者是目录不存在的时候!
    	File file=new File("...");
    	File []arr=file.listFile();
    	if(arr!=null){
    		//加判断避免异常...
    		}
    	}
    }		
    }
    展开全文
  • 在调用系统相机、相册时,经常需要进行Uri和File路径的互相转换,并且在项目中遇到按照百度查到的...Android 7.0以下,以文件路径创建File对象,然后调用Uri.fromFile(file)即可获得相应的Uri。 //创建临时图...

    在调用系统相机、相册时,经常需要进行Uri和File路径的互相转换,并且在项目中遇到按照百度查到的处理7.0方法分享文件到微信的7.0之后版本会文件名后缀被增加了..octet.stream无法解决,最终使用强制转换方法解决问题。

    文件路径转Uri

    Android 7.0以下,以文件路径创建一个File对象,然后调用Uri.fromFile(file)即可获得相应的Uri。

    //创建临时图片
    File photoOutputFile = SDPath.getFile("temp.jpg", SDPath.PHOTO_FILE_STR);
    Uri photoOutputUri = Uri.fromFile(photoOutputFile);

    但是在Android 7.0 (N) 以上,对于面向 Android 7.0 的应用,Android 框架执行的 StrictMode API 政策禁止在应用外部公开 file:// URI,即当把targetSdkVersion指定成24及之上并且在API>=24的设备上运行时,如果一项包含文件 URI 的 intent 离开应用(如分享),则应用出现故障,并出现 FileUriExposedException 异常。

    android.os.FileUriExposedException:         file:///XXX exposed beyond app through ClipData.Item.getUri()
        at android.os.StrictMode.onFileUriExposed(StrictMode.java:1799)
        at android.net.Uri.checkFileUriExposed(Uri.java:2346)
        at android.content.ClipData.prepareToLeaveProcess(ClipData.java:832)
        at android.content.Intent.prepareToLeaveProcess(Intent.java:8909)
        ...
    

    查看7.0文档如下

    原因在于使用file://Uri会有一些风险,比如:

    • 文件是私有的,接收file://Uri的app无法访问该文件。
    • 在Android6.0之后引入运行时权限,如果接收file://Uri的app没有申请READ_EXTERNAL_STORAGE权限,在读取文件时会引发崩溃。

    因此,google提供了FileProvider 类,使用它可以生成content://Uri来替代file://Uri,所以要在应用间共享文件,应发送一项 content:// URI,并授予 URI 临时访问权限。

    FileProvider是android support v4包提供的,是ContentProvider的子类,便于将自己app的数据提供给其他app访问。
            在app开发过程中需要用到FileProvider的主要有

    • 相机拍照以及图片裁剪
    • 调用系统应用安装器安装apk(应用升级)
    • 分享文件

    使用content://Uri的优点:

    • 它可以控制共享文件的读写权限,只要调用Intent.setFlags()就可以设置对方app对共享文件的访问权限,并且该权限在对方app退出后自动失效。相比之下,使用file://Uri时只能通过修改文件系统的权限来实现访问控制,这样的话访问控制是它对所有 app都生效的,不能区分app。
    • 它可以隐藏共享文件的真实路径。

    file://到content://的转换规则:

    a.替换前缀:把file://替换成content://${android:authorities}。
    b.匹配和替换

    • 遍历<paths>的子节点,找到最大能匹配上文件路径前缀的那个子节点。
    • 用path的值替换掉文件路径里所匹配的内容。

    c.文件路径剩余的部分保持不变.

     

    解决方案

    ①定义FileProvider。在AndroidManifest.xml中加上自定义权限的ContentProvider,在<application>节点中添加<provider>如下

    <provider  
                android:name="android.support.v4.content.FileProvider"  
                android:authorities="com.php.demo.FileProvider"  
                android:exported="false"  
                android:grantUriPermissions="true">  
                <meta-data  
                    android:name="android.support.FILE_PROVIDER_PATHS"  
                    android:resource="@xml/file_paths" />  
            </provider>  
    

    说明:

    android:authorities="com.php.demo.FileProvider" 用来标识provider的唯一标识,在同一部手机上一个"authority"串只能被一个app使用,冲突的话会导致app无法安装。我们可以利用manifest placeholders(包名)来保证authority的唯一性。

    android:exported="false" 是否设置为独立进程,必须设置成false,否则运行时会报错java.lang.SecurityException: Provider must not be exported

    android:grantUriPermissions="true" 是否拥有共享文件的临时权限,也可以在java代码中设置。

    android:resource="@xml/external_storage_root" 共享文件的文件根目录,名字可以自定义

    ②指定路径和转换规则。FileProvider会隐藏共享文件的真实路径,将它转换成content://Uri路径,因此,我们还需要设定转换的规则。在项目res目录下创建一个xml文件夹,里面创建一个file_paths.xml文件,上一步定义的什么名称,这里就什么名称,如图:

    <?xml version="1.0" encoding="utf-8"?>
    <paths>
        <external-path
            name="external_storage_root"
            path="." />
        <files-path
            name="files-path"
            path="." />
        <cache-path
            name="cache-path"
            path="." />
        <!--/storage/emulated/0/Android/data/...-->
        <external-files-path
            name="external_file_path"
            path="." />
        <!--代表app 外部存储区域根目录下的文件 Context.getExternalCacheDir目录下的目录-->
        <external-cache-path
            name="external_cache_path"
            path="." />
        <!--配置root-path。这样子可以读取到sd卡和一些应用分身的目录,否则微信分身保存的图片,就会导致 java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/999/tencent/MicroMsg/WeiXin/export1544062754693.jpg,在小米6的手机上微信分身有这个crash,华为没有
    -->
        <root-path
            name="root-path"
            path="" />
    /paths>
    

    这个配置的标签参照FileProvider里面的TAG配置。

    在这里插入图片描述

    root-path 对应DEVICE_ROOT,也就是File DEVICE_ROOT = new File("/"),即根目录,一般不需要配置。
    files-path对应 content.getFileDir() 获取到的目录。
    cache-path对应 content.getCacheDir() 获取到的目录
    external-path对应 Environment.getExternalStorageDirectory() 指向的目录。
    external-files-path对应 ContextCompat.getExternalFilesDirs() 获取到的目录。
    external-cache-path对应 ContextCompat.getExternalCacheDirs() 获取到的目录。

    TAG Value Path
    TAG_ROOT_PATH root-path /
    TAG_FILES_PATH files-path /data/data/<包名>/files
    TAG_CACHE_PATH cache-path /data/data/<包名>/cache
    TAG_EXTERNAL external-path /storage/emulate/0
    TAG_EXTERNAL_FILES external-files-path /storage/emulate/0/Android/data/<包名>/files
    TAG_EXTERNAL_CACHE external-cache-path /storage/emulate/0/Android/data/<包名>/cache

    首先介绍些基础知识:Android的文件系统和MediaStore类的使用
    外部存储的公共目录
    DIRECTORY_MUSIC:音乐类型 /storage/emulate/0/music
    DIRECTORY_PICTURES:图片类型
    DIRECTORY_MOVIES:电影类型
    DIRECTORY_DCIM:照片类型,相机拍摄的照片视频都在这个目录(digital camera in memory) /storage/emulate/0/DCIM
    DIRECTORY_DOWNLOADS:下载文件类型 /storage/emulate/0/downloads
    DIRECTORY_DOCUMENTS:文档类型
    DIRECTORY_RINGTONES:铃声类型
    DIRECTORY_ALARMS:闹钟提示音类型
    DIRECTORY_NOTIFICATIONS:通知提示音类型
    DIRECTORY_PODCASTS:播客音频类型

    这些可以通过Environment的getExternalStoragePublicDirectory()来获取

     安卓系统会在每次开机之后扫描所有文件并分类整理存入数据库,记录在MediaStore这个类里,通过这个类就可以快速的获得相应类型的文件。当然这个类只是给你一个uri,提取文件的操作还是要通过Curosr这个类来完成。获得Cursor对象实例的方法必须通过Context实例获得ContextResolver对象,通过这个对象调用query方法。

    就是这样 mycontext.getContentResolver().query(uri, columns, selection, null, null);

    mycontext通过活动实例获取,其他的就没必要说了 说说参数(官方文档里有详细说明),第一个就是uri说白了就是地址,第二个是选择哪些列(列的名字在官方文档里有需要哪个写那个就够了),第三个是选择指定的行一般都是通过mimetype去选择(传入的参数是sql语句的字符串),第四个没用过,第五个就是排序的要求和第三个差不多 注意前三个参数有点问题就会空指针。
      下面贴一下通过MediaStore类获得URI的代码

    private Uri getContentUri(FileCategory cat) {
            Uri uri;
            String volumeName = "external";
            switch(cat) {
                case Theme:
                case Doc:
                case Zip:
                case Apk:
                    uri = Files.getContentUri(volumeName);
                    break;
                case Music:
                    uri = Audio.Media.getContentUri(volumeName);
                    break;
                case Video:
                    uri = Video.Media.getContentUri(volumeName);
                    break;
                case Picture:
                    uri = Images.Media.getContentUri(volumeName);
                    break;
               default:
                   uri = null;
            }
            Log.e(LOG_CURSOR, "getContentUri");
            return uri;
        }

     

    接下来以系统分享功能为例,解决“获取资源失败”和fileprovider生成的uri地址,应用不能识别问题,是要把uri地址转换一下。

    要调用 Android 系统内建的分享功能,主要有三步流程:

    • 创建一个 Intent ,指定其 Action 为 Intent.ACTION_SEND,表示要创建一个发送指定内容的隐式意图。
    • 然后指定需要发送的内容和类型,设置分享的文本内容或文件的Uri,以及文件的类型,便于是支持该类型内容的应用打开。
    • 最后向系统发送隐式意图,开启系统分享选择器,分享完成后收到结果返回。

    知道大致的实现流程后,其实只要解决下面几个问题后就可以具体实施了。

    确定要分享的内容类型

    这其实是直接决定了最终的实现形态,我们知道常见的使用场景中,只是为了在应用间分享图片和一些文件,那对于那些只是分享文本的产品而言,两者实现起来要考虑的问题完全不同。

    所以为了解决这个问题,我们可以预先定好支持的分享内容类型,针对不同类型可以进行不同的处理。

    @StringDef({ShareContentType.TEXT, ShareContentType.IMAGE,
            ShareContentType.AUDIO, ShareContentType.VIDEO, ShareContentType.File})
    @Retention(RetentionPolicy.SOURCE)
    @interface ShareContentType {
        /**
         * Share Text
         */
        final String TEXT = "text/plain";
    
        /**
         * Share Image
         */
        final String IMAGE = "image/*";
    
        /**
         * Share Audio
         */
        final String AUDIO = "audio/*";
    
        /**
         * Share Video
         */
        final String VIDEO = "video/*";
    
        /**
         * Share File
         */
        final String File = "*/*";
    }`

    上述一共定义了5种类别的分享内容,基本能覆盖常见的使用场景。在调用分享接口时可以直接指定内容类型,比如像文本、图片、音视频、及其他各种类型文件。

    确定分享的内容来源

    比如调用系统相机进行拍照或录制音视频,要传入一个生成目标文件的 Uri

     private static final int REQUEST_FILE_SELECT_CODE = 100;
       /**
         * 打开系统相机进行拍照
         */
        private void openSystemCamera() {
            //调用系统相机
            Intent takePhotoIntent = new Intent();
            takePhotoIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
    
            if (takePhotoIntent.resolveActivity(getPackageManager()) == null) {
                Toast.makeText(this, "当前系统没有可用的相机应用", Toast.LENGTH_SHORT).show();
                return;
            }
    
            String fileName = "TEMP_" + System.currentTimeMillis() + ".jpg";
            File photoFile = new File(FileUtil.getPhotoCacheFolder(), fileName);
    
            // 7.0和以上版本的系统要通过 FileProvider 创建一个 content 类型的 Uri
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                currentTakePhotoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileProvider", photoFile);
                takePhotoIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION|);
            } else {
                currentTakePhotoUri = Uri.fromFile(photoFile);
            }
    
            //将拍照结果保存至 outputFile 的Uri中,不保留在相册中
            takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT, currentTakePhotoUri);
            startActivityForResult(takePhotoIntent, TAKE_PHOTO_REQUEST_CODE);
        }
    
         // 调用系统相机进行拍照与上面通过文件选择器获得文件 uri 的方式类似
         // 在 onActivityResult 进行回调处理,此时 Uri 是你 FileProvider 中指定的,注意与文件选择器获取的 Uri 的区别。

    分享文件 Uri 的处理

    要对应用进行临时访问 Uri 的授权才行,不然会提示权限缺失。对于要分享系统返回的 Uri 我们可以这样进行处理:

    // 可以对发起分享的 Intent 添加临时访问授权
    shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    
    // 也可以这样:由于不知道最终用户会选择哪个app,所以授予所有应用临时访问权限
    if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
        List<ResolveInfo> resInfoList = activity.getPackageManager().queryIntentActivities(shareIntent, PackageManager.MATCH_DEFAULT_ONLY);
        for (ResolveInfo resolveInfo : resInfoList) {
            String packageName = resolveInfo.activityInfo.packageName;
            activity.grantUriPermission(packageName, shareFileUri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
    }

    需要注意的是对于自定义 FileProvider 返回 Uri 的处理,即使是设置临时访问权限,但是分享到第三方应用也会无法识别该 Uri

    典型的场景就是,我们如果把自定义 FileProvider 的返回的 Uri 设置分享到微信或 QQ 之类的第三方应用,会提示文件不存在,这是因为他们无法识别该 Uri。

    关于这个问题的处理其实跟下面要说的把文件路径变成系统返回的 Uri 一样,我们只需要把自定义 FileProvider 返回的 Uri 变成第三方应用可以识别系统返回的 Uri 就行了。

    创建 FileProvider 时需要传入一个 File 对象,所以直接可以知道文件路径,那就把问题都转换成了:如何通过文件路径获取系统返回的 Uri

    本人在项目中获取本地文件如下:

    Intent share = new Intent(Intent.ACTION_SEND);
            File file = new File(filePath);
            Uri contentUri = null;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                share.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                contentUri = DealFileClass.getFileUri(getActivity(),DealFileClass.ShareContentType.File,file);
                share.putExtra(Intent.EXTRA_STREAM, contentUri);
                share.setType("application/pdf");// 此处可发送多种文件
            } else {
                share.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
                share.setType("application/pdf");// 此处可发送多种文件
            }
            try{
                startActivity(Intent.createChooser(share, "Share"));
            } catch (Exception e) {
                e.printStackTrace();
            }

    下面是根据传入的 File 对象和类型来查询系统 ContentProvider 来获取相应的 Uri,已经按照不同文件类型在不同系统版本下的进行了适配。

    其中 forceGetFileUri 方法是通过反射实现的,处理 7.0 以上系统的特殊情况下的兼容性,一般情况下不会调用到。Android 7.0 开始不允许 file:// Uri 的方式在不同的 App 间共享文件,但是如果换成 FileProvider 的方式依然是无效的,我们可以通过反射把该检测干掉。

    public static Uri getFileUri (Context context, @ShareContentType String shareContentType, File file){
    
            if (context == null) {
                Log.e(TAG,"getFileUri current activity is null.");
                return null;
            }
    
            if (file == null || !file.exists()) {
                Log.e(TAG,"getFileUri file is null or not exists.");
                return null;
            }
    
            Uri uri = null;
            
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
                uri = Uri.fromFile(file);
            } else {
    
                if (TextUtils.isEmpty(shareContentType)) {
                    shareContentType = "*/*";
                }
    
                switch (shareContentType) {
                    case ShareContentType.IMAGE :
                        uri = getImageContentUri(context, file);
                        break;
                    case ShareContentType.VIDEO :
                        uri = getVideoContentUri(context, file);
                        break;
                    case ShareContentType.AUDIO :
                        uri = getAudioContentUri(context, file);
                        break;
                    case ShareContentType.File :
                        uri = getFileContentUri(context, file);
                        break;
                    default: break;
                }
            }
            
            if (uri == null) {
                uri = forceGetFileUri(file);
            }
            
            return uri;
        }
    
    
        private static Uri getFileContentUri(Context context, File file) {
            String volumeName = "external";
            String filePath = file.getAbsolutePath();
            String[] projection = new String[]{MediaStore.Files.FileColumns._ID};
            Uri uri = null;
    
            Cursor cursor = context.getContentResolver().query(MediaStore.Files.getContentUri(volumeName), projection,
                    MediaStore.Images.Media.DATA + "=? ", new String[] { filePath }, null);
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Files.FileColumns._ID));
                    uri = MediaStore.Files.getContentUri(volumeName, id);
                }
                cursor.close();
            }
    
            return uri;
        }
    
        private static Uri getImageContentUri(Context context, File imageFile) {
            String filePath = imageFile.getAbsolutePath();
            Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    new String[] { MediaStore.Images.Media._ID }, MediaStore.Images.Media.DATA + "=? ",
                    new String[] { filePath }, null);
            Uri uri = null;
    
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
                    Uri baseUri = Uri.parse("content://media/external/images/media");
                    uri = Uri.withAppendedPath(baseUri, "" + id);
                }
                
                cursor.close();
            }
            
            if (uri == null) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Images.Media.DATA, filePath);
                uri = context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            }
    
            return uri;
        }
    
        private static Uri getVideoContentUri(Context context, File videoFile) {
            Uri uri = null;
            String filePath = videoFile.getAbsolutePath();
            Cursor cursor = context.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                    new String[] { MediaStore.Video.Media._ID }, MediaStore.Video.Media.DATA + "=? ",
                    new String[] { filePath }, null);
            
            if (cursor != null) { 
                if (cursor.moveToFirst()) { 
                    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
                    Uri baseUri = Uri.parse("content://media/external/video/media");
                    uri = Uri.withAppendedPath(baseUri, "" + id);
                }
                
                cursor.close();
            } 
            
            if (uri == null) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Video.Media.DATA, filePath);
                uri = context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
            }
            
            return uri;
        }
    
    
        private static Uri getAudioContentUri(Context context, File audioFile) {
            Uri uri = null;
            String filePath = audioFile.getAbsolutePath();
            Cursor cursor = context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                    new String[] { MediaStore.Audio.Media._ID }, MediaStore.Audio.Media.DATA + "=? ",
                    new String[] { filePath }, null);
            
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
                    Uri baseUri = Uri.parse("content://media/external/audio/media");
                    uri = Uri.withAppendedPath(baseUri, "" + id);
                }
                
                cursor.close();
            }
            if (uri == null) {
                ContentValues values = new ContentValues();
                values.put(MediaStore.Audio.Media.DATA, filePath);
                uri = context.getContentResolver().insert(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, values);
            } 
            
            return uri;
        }
    
        private static Uri forceGetFileUri(File shareFile) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                try {
                    @SuppressLint("PrivateApi")
                    Method rMethod = StrictMode.class.getDeclaredMethod("disableDeathOnFileUriExposure");
                    rMethod.invoke(null);
                } catch (Exception e) {
                    Log.e(TAG, Log.getStackTraceString(e));
                }
            }
    
            return Uri.parse("file://" + shareFile.getAbsolutePath());
        }


    此外,如若uri要转换为文件路径则可如下处理(以内部存储默认某第三方应用打开某格式文件为例):

    清单文件中进行申明:

    <activity
                android:name="com.php.FileActivity"
                android:allowTaskReparenting="true"
                android:launchMode="singleTask"
                android:configChanges="orientation|keyboard|keyboardHidden"
                android:screenOrientation="portrait"
                android:theme="@style/fileStyle">
    
                <!-- 将activity与PDF文件关联 -->
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data
                        android:mimeType="application/pdf"
                        android:scheme="file"></data>
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data
                        android:mimeType="application/pdf"
                        android:scheme="content"></data>
                </intent-filter>
                <!-- 将activity与EDC文件关联 -->
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:scheme="file" />
                    <data android:mimeType="*/*" />
                    <data android:host="*" />
                    <data android:pathPattern=".*\\.edc" />
                </intent-filter>
                <intent-filter>
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <data android:scheme="content" />
                    <data android:mimeType="*/*" />
                    <data android:host="*" />
                    <data android:pathPattern=".*\\.edc" />
                </intent-filter>
               
            </activity>


    类文件中:

    Intent intent = getIntent();
    String action = intent.getAction();
    
    if (Intent.ACTION_VIEW.equals(action)) {
                Uri uri = intent.getData();
                String filename = uri.getPath();
                if (String.valueOf(uri) != null && String.valueOf(uri).contains("content")) {
                    boolean kkk = false;
                    try{
                        filename = CommonUtils.getFilePathFromContentUri(uri,this.getContentResolver());
                        if(CommonUtils.isEmpty(filename)){
                            kkk = true;
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                        kkk = true;
                    }
                    if(kkk){
                        filename = ProviderUtils.getFPUriToPath(this,uri);
                    }
                }
             
            }

    其中,getFilePathFromContentUri如下:

    /**
         * 将uri转换成真实路径
         *
         * @param selectedVideoUri
         * @param contentResolver
         * @return
         */
        public static String getFilePathFromContentUri(Uri selectedVideoUri,
                                                       ContentResolver contentResolver) {
            String filePath = "";
            String[] filePathColumn = {MediaColumns.DATA};
    
            Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn,
                    null, null, null);
            // 也可用下面的方法拿到cursor
            // Cursor cursor = this.context.managedQuery(selectedVideoUri,
            // filePathColumn, null, null, null);
    
    //        cursor.moveToFirst();
    //
    //        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    //        filePath = cursor.getString(columnIndex);
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    int id = cursor.getColumnIndex(filePathColumn[0]);
                    if(id > -1)
                        filePath = cursor.getString(id);
                }
                cursor.close();
            }
    
            return filePath;
        }

    ProviderUtils类文件内容如下:

    public class ProviderUtils {
    
        public static String getFPUriToPath(Context context, Uri uri) {
            try {
                List<PackageInfo> packs = context.getPackageManager().getInstalledPackages(PackageManager.GET_PROVIDERS);
                if (packs != null) {
                    String fileProviderClassName = FileProvider.class.getName();
                    for (PackageInfo pack : packs) {
                        ProviderInfo[] providers = pack.providers;
                        if (providers != null) {
                            for (ProviderInfo provider : providers) {
                                if (uri.getAuthority().equals(provider.authority)) {
                                    if (provider.name.equalsIgnoreCase(fileProviderClassName)) {
                                        Class<FileProvider> fileProviderClass = FileProvider.class;
                                        try {
                                            Method getPathStrategy = fileProviderClass.getDeclaredMethod("getPathStrategy", Context.class, String.class);
                                            getPathStrategy.setAccessible(true);
                                            Object invoke = getPathStrategy.invoke(null, context, uri.getAuthority());
                                            if (invoke != null) {
                                                String PathStrategyStringClass = FileProvider.class.getName() + "$PathStrategy";
                                                Class<?> PathStrategy = Class.forName(PathStrategyStringClass);
                                                Method getFileForUri = PathStrategy.getDeclaredMethod("getFileForUri", Uri.class);
                                                getFileForUri.setAccessible(true);
                                                Object invoke1 = getFileForUri.invoke(invoke, uri);
                                                if (invoke1 instanceof File) {
                                                    String filePath = ((File) invoke1).getAbsolutePath();
                                                    return filePath;
                                                }
                                            }
                                        } catch (NoSuchMethodException e) {
                                            e.printStackTrace();
                                        } catch (InvocationTargetException e) {
                                            e.printStackTrace();
                                        } catch (IllegalAccessException e) {
                                            e.printStackTrace();
                                        } catch (ClassNotFoundException e) {
                                            e.printStackTrace();
                                        }
                                        break;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    最后欢迎大家关注我个人公众号,可以一起交流成长。

    展开全文
  • 不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,... 笔者先学的caffe,从使用来看,比caffe简单超级多,非常好用,特别是重新训练个模型,但是

    不得不说,这深度学习框架更新太快了尤其到了Keras2.0版本,快到Keras中文版好多都是错的,快到官方文档也有旧的没更新,前路坑太多。
    到发文为止,已经有theano/tensorflow/CNTK支持keras,虽然说tensorflow造势很多,但是笔者认为接下来Keras才是正道。
    笔者先学的caffe,从使用来看,比caffe简单超级多,非常好用,特别是重新训练一个模型,但是呢,在fine-tuning的时候,遇到了很多问题,对新手比较棘手。

    中文文档:http://keras-cn.readthedocs.io/en/latest/
    官方文档:https://keras.io/
    文档主要是以keras2.0。


    .

    Keras系列:

    1、keras系列︱Sequential与Model模型、keras基本结构功能(一)
    2、keras系列︱Application中五款已训练模型、VGG16框架(Sequential式、Model式)解读(二)
    3、keras系列︱图像多分类训练与利用bottleneck features进行微调(三)
    4、keras系列︱人脸表情分类与识别:opencv人脸检测+Keras情绪分类(四)
    5、keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完整案例(五)


    零、keras介绍与基本的模型保存

    写成了思维导图,便于观察与理解。

    1.keras网络结构

    这里写图片描述
    ###2.keras网络配置
    这里写图片描述
    其中回调函数callbacks应该是keras的精髓~
    ###3.keras预处理功能
    这里写图片描述

    ###4、模型的节点信息提取

    # 节点信息提取
    config = model.get_config()  # 把model中的信息,solver.prototxt和train.prototxt信息提取出来
    model = Model.from_config(config)  # 还回去
    # or, for Sequential:
    model = Sequential.from_config(config) # 重构一个新的Model模型,用去其他训练,fine-tuning比较好用
    

    ###5、 模型概况查询(包括权重查询)

    # 1、模型概括打印
    model.summary()
    
    # 2、返回代表模型的JSON字符串,仅包含网络结构,不包含权值。可以从JSON字符串中重构原模型:
    from models import model_from_json
    
    json_string = model.to_json()
    model = model_from_json(json_string)
    
    # 3、model.to_yaml:与model.to_json类似,同样可以从产生的YAML字符串中重构模型
    from models import model_from_yaml
    
    yaml_string = model.to_yaml()
    model = model_from_yaml(yaml_string)
    
    # 4、权重获取
    model.get_layer()      #依据层名或下标获得层对象
    model.get_weights()    #返回模型权重张量的列表,类型为numpy array
    model.set_weights()    #从numpy array里将权重载入给模型,要求数组具有与model.get_weights()相同的形状。
    
    # 查看model中Layer的信息
    model.layers 查看layer信息
    
    

    ###6、模型保存与加载

    model.save_weights(filepath)
    # 将模型权重保存到指定路径,文件类型是HDF5(后缀是.h5)
    
    model.load_weights(filepath, by_name=False)
    # 从HDF5文件中加载权重到当前模型中, 默认情况下模型的结构将保持不变。
    # 如果想将权重载入不同的模型(有些层相同)中,则设置by_name=True,只有名字匹配的层才会载入权重
    

    .

    7、如何在keras中设定GPU使用的大小

    本节来源于:深度学习theano/tensorflow多显卡多人使用问题集(参见:Limit the resource usage for tensorflow backend · Issue #1538 · fchollet/keras · GitHub
    在使用keras时候会出现总是占满GPU显存的情况,可以通过重设backend的GPU占用情况来进行调节。

    import tensorflow as tf
    from keras.backend.tensorflow_backend import set_session
    config = tf.ConfigProto()
    config.gpu_options.per_process_gpu_memory_fraction = 0.3
    set_session(tf.Session(config=config))
    

    需要注意的是,虽然代码或配置层面设置了对显存占用百分比阈值,但在实际运行中如果达到了这个阈值,程序有需要的话还是会突破这个阈值。换而言之如果跑在一个大数据集上还是会用到更多的显存。以上的显存限制仅仅为了在跑小数据集时避免对显存的浪费而已。(2017年2月20日补充)

    8.更科学地模型训练与模型保存

    filepath = 'model-ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5'
    checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_best_only=True, mode='min')
    # fit model
    model.fit(x, y, epochs=20, verbose=2, callbacks=[checkpoint], validation_data=(x, y))
    

    save_best_only打开之后,会如下:

     ETA: 3s - loss: 0.5820Epoch 00017: val_loss did not improve
    

    如果val_loss 提高了就会保存,没有提高就不会保存。

    9.如何在keras中使用tensorboard

        RUN = RUN + 1 if 'RUN' in locals() else 1   # locals() 函数会以字典类型返回当前位置的全部局部变量。
    
        LOG_DIR = model_save_path + '/training_logs/run{}'.format(RUN)
        LOG_FILE_PATH = LOG_DIR + '/checkpoint-{epoch:02d}-{val_loss:.4f}.hdf5'   # 模型Log文件以及.h5模型文件存放地址
    
        tensorboard = TensorBoard(log_dir=LOG_DIR, write_images=True)
        checkpoint = ModelCheckpoint(filepath=LOG_FILE_PATH, monitor='val_loss', verbose=1, save_best_only=True)
        early_stopping = EarlyStopping(monitor='val_loss', patience=5, verbose=1)
    
        history = model.fit_generator(generator=gen.generate(True), steps_per_epoch=int(gen.train_batches / 4),
                                      validation_data=gen.generate(False), validation_steps=int(gen.val_batches / 4),
                                      epochs=EPOCHS, verbose=1, callbacks=[tensorboard, checkpoint, early_stopping])
    

    都是在回调函数中起作用:

    • EarlyStopping patience:当early
      (1)stop被激活(如发现loss相比上一个epoch训练没有下降),则经过patience个epoch后停止训练。
      (2)mode:‘auto’,‘min’,‘max’之一,在min模式下,如果检测值停止下降则中止训练。在max模式下,当检测值不再上升则停止训练。

    • 模型检查点ModelCheckpoint
      (1)save_best_only:当设置为True时,将只保存在验证集上性能最好的模型
      (2) mode:‘auto’,‘min’,‘max’之一,在save_best_only=True时决定性能最佳模型的评判准则,例如,当监测值为val_acc时,模式应为max,当检测值为val_loss时,模式应为min。在auto模式下,评价准则由被监测值的名字自动推断。
      (3)save_weights_only:若设置为True,则只保存模型权重,否则将保存整个模型(包括模型结构,配置信息等)
      (4)period:CheckPoint之间的间隔的epoch数

    • 可视化tensorboard write_images: 是否将模型权重以图片的形式可视化

    其他内容可参考keras中文文档

    .


    一、Sequential 序贯模型

    序贯模型是函数式模型的简略版,为最简单的线性、从头到尾的结构顺序,不分叉。

    Sequential模型的基本组件

    一般需要:

    • 1、model.add,添加层;
    • 2、model.compile,模型训练的BP模式设置;
    • 3、model.fit,模型训练参数设置 + 训练;
    • 4、模型评估
    • 5、模型预测

    1. add:添加层——train_val.prototxt

    add(self, layer)
    
    # 譬如:
    model.add(Dense(32, activation='relu', input_dim=100))
    model.add(Dropout(0.25))
    

    add里面只有层layer的内容,当然在序贯式里面,也可以model.add(other_model)加载另外模型,在函数式里面就不太一样,详见函数式。

    2、compile 训练模式——solver.prototxt文件

    compile(self, optimizer, loss, metrics=None, sample_weight_mode=None)
    

    其中:
    optimizer: 字符串(预定义优化器名)或优化器对象,参考优化器
    loss: 字符串(预定义损失函数名)或目标函数,参考损失函数
    metrics: 列表,包含评估模型在训练和测试时的网络性能的指标,典型用法是metrics=[‘accuracy’]
    sample_weight_mode:如果你需要按时间步为样本赋权(2D权矩阵),将该值设为“temporal”。
    默认为“None”,代表按样本赋权(1D权)。在下面fit函数的解释中有相关的参考内容。
    kwargs: 使用TensorFlow作为后端请忽略该参数,若使用Theano作为后端,kwargs的值将会传递给 K.function

    注意:
    模型在使用前必须编译,否则在调用fit或evaluate时会抛出异常。

    3、fit 模型训练参数+训练——train.sh+soler.prototxt(部分)

    fit(self, x, y, batch_size=32, epochs=10, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)
    

    本函数将模型训练nb_epoch轮,其参数有:

    • x:输入数据。如果模型只有一个输入,那么x的类型是numpy
      array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy array
    • y:标签,numpy array
    • batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
    • epochs:整数,训练的轮数,每个epoch会把训练集轮一遍。
    • verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
    • callbacks:list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数
    • validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。
    • validation_data:形式为(X,y)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
    • shuffle:布尔值或字符串,一般为布尔值,表示是否在训练过程中随机打乱输入样本的顺序。若为字符串“batch”,则是用来处理HDF5数据的特殊情况,它将在batch内部将数据打乱。
    • class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)
    • sample_weight:权值的numpy
      array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=‘temporal’。
    • initial_epoch: 从该参数指定的epoch开始训练,在继续之前的训练时有用。

    fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况
    注意:
    要与之后的fit_generator做区别,两者输入x/y不同。

    4.evaluate 模型评估

    evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
    

    本函数按batch计算在某些输入数据上模型的误差,其参数有:

    • x:输入数据,与fit一样,是numpy array或numpy array的list
    • y:标签,numpy array
    • batch_size:整数,含义同fit的同名参数
    • verbose:含义同fit的同名参数,但只能取0或1
    • sample_weight:numpy array,含义同fit的同名参数

    本函数返回一个测试误差的标量值(如果模型没有其他评价指标),或一个标量的list(如果模型还有其他的评价指标)。model.metrics_names将给出list中各个值的含义。

    如果没有特殊说明,以下函数的参数均保持与fit的同名参数相同的含义
    如果没有特殊说明,以下函数的verbose参数(如果有)均只能取0或1

    5 predict 模型评估

    predict(self, x, batch_size=32, verbose=0)
    predict_classes(self, x, batch_size=32, verbose=1)
    predict_proba(self, x, batch_size=32, verbose=1)
    

    本函数按batch获得输入数据对应的输出,其参数有:

    函数的返回值是预测值的numpy array
    predict_classes:本函数按batch产生输入数据的类别预测结果;
    predict_proba:本函数按batch产生输入数据属于各个类别的概率

    6 on_batch 、batch的结果,检查

    train_on_batch(self, x, y, class_weight=None, sample_weight=None)
    test_on_batch(self, x, y, sample_weight=None)
    predict_on_batch(self, x)
    
    • train_on_batch:本函数在一个batch的数据上进行一次参数更新,函数返回训练误差的标量值或标量值的list,与evaluate的情形相同。
    • test_on_batch:本函数在一个batch的样本上对模型进行评估,函数的返回与evaluate的情形相同
    • predict_on_batch:本函数在一个batch的样本上对模型进行测试,函数返回模型在一个batch上的预测结果

    7 fit_generator

    #利用Python的生成器,逐个生成数据的batch并进行训练。
    #生成器与模型将并行执行以提高效率。
    #例如,该函数允许我们在CPU上进行实时的数据提升,同时在GPU上进行模型训练
    # 参考链接:http://keras-cn.readthedocs.io/en/latest/models/sequential/
    

    有了该函数,图像分类训练任务变得很简单。

    fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_q_size=10, workers=1, pickle_safe=False, initial_epoch=0)
    
    # 案例:
    def generate_arrays_from_file(path):
        while 1:
                f = open(path)
                for line in f:
                    # create Numpy arrays of input data
                    # and labels, from each line in the file
                    x, y = process_line(line)
                    yield (x, y)
            f.close()
    
    model.fit_generator(generate_arrays_from_file('/my_file.txt'),
            samples_per_epoch=10000, epochs=10)
    

    其他的两个辅助的内容:

    evaluate_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False)
    predict_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False, verbose=0)
    

    evaluate_generator:本函数使用一个生成器作为数据源评估模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。
    predcit_generator:本函数使用一个生成器作为数据源预测模型,生成器应返回与test_on_batch的输入数据相同类型的数据。该函数的参数与fit_generator同名参数含义相同,steps是生成器要返回数据的轮数。

    案例一:简单的2分类

    For a single-input model with 2 classes (binary classification):

    from keras.models import Sequential
    from keras.layers import Dense, Activation
    
    #模型搭建阶段
    model= Sequential()
    model.add(Dense(32, activation='relu', input_dim=100))
    # Dense(32) is a fully-connected layer with 32 hidden units.
    model.add(Dense(1, activation='sigmoid'))
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    

    其中:
    Sequential()代表类的初始化;
    Dense代表全连接层,此时有32个神经元,最后接relu,输入的是100维度
    model.add,添加新的全连接层,
    compile,跟prototxt一样,一些训练参数,solver.prototxt

    # Generate dummy data
    import numpy as np
    data = np.random.random((1000, 100))
    labels = np.random.randint(2, size=(1000, 1))
    
    # Train the model, iterating on the data in batches of 32 samples
    model.fit(data, labels, nb_epoch =10, batch_size=32)
    

    之前报过这样的错误,是因为版本的问题。 版本1.2里面是nb_epoch ,而keras2.0是epochs = 10

     error:
        TypeError: Received unknown keyword arguments: {'epochs': 10}
    

    其中:
    epoch=batch_size * iteration,10次epoch代表训练十次训练集

    案例二:多分类-VGG的卷积神经网络

    import numpy as np
    import keras
    from keras.models import Sequential
    from keras.layers import Dense, Dropout, Flatten
    from keras.layers import Conv2D, MaxPooling2D
    from keras.optimizers import SGD
    from keras.utils import np_utils
    
    # Generate dummy data
    x_train = np.random.random((100, 100, 100, 3))
    # 100张图片,每张100*100*3
    y_train = keras.utils.to_categorical(np.random.randint(10, size=(100, 1)), num_classes=10)
    # 100*10
    x_test = np.random.random((20, 100, 100, 3))
    y_test = keras.utils.to_categorical(np.random.randint(10, size=(20, 1)), num_classes=10)
    # 20*100
    
    model = Sequential()
    # input: 100x100 images with 3 channels -> (100, 100, 3) tensors.
    # this applies 32 convolution filters of size 3x3 each.
    model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(100, 100, 3)))
    model.add(Conv2D(32, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.25))
    
    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(10, activation='softmax'))
    
    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='categorical_crossentropy', optimizer=sgd)
    
    model.fit(x_train, y_train, batch_size=32, epochs=10)
    score = model.evaluate(x_test, y_test, batch_size=32)
    

    标准序贯网络,标签的训练模式
    注意:
    这里非常重要的一点,对于我这样的新手,这一步的作用?

    keras.utils.to_categorical
    

    特别是多分类时候,我之前以为输入的就是一列(100,),但是keras在多分类任务中是不认得这个的,所以需要再加上这一步,让其转化为Keras认得的数据格式。

    案例三:使用LSTM的序列分类

    from keras.models import Sequential
    from keras.layers import Dense, Dropout
    from keras.layers import Embedding
    from keras.layers import LSTM
    
    model = Sequential()
    model.add(Embedding(max_, output_dim=256))
    model.add(LSTM(128))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))
    
    model.compile(loss='binary_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    
    model.fit(x_train, y_train, batch_size=16, epochs=10)
    score = model.evaluate(x_test, y_test, batch_size=16)
    

    .


    三、Model式模型

    来自keras中文文档:http://keras-cn.readthedocs.io/en/latest/
    比序贯模型要复杂,但是效果很好,可以同时/分阶段输入变量,分阶段输出想要的模型;
    一句话,只要你的模型不是类似VGG一样一条路走到黑的模型,或者你的模型需要多于一个的输出,那么你总应该选择函数式模型。

    不同之处:
    书写结构完全不一致

    函数式模型基本属性与训练流程

    一般需要:
    1、model.layers,添加层信息;
    2、model.compile,模型训练的BP模式设置;
    3、model.fit,模型训练参数设置 + 训练;
    4、evaluate,模型评估;
    5、predict 模型预测

    1 常用Model属性

    model.layers:组成模型图的各个层
    model.inputs:模型的输入张量列表
    model.outputs:模型的输出张量列表
    

    2 compile 训练模式设置——solver.prototxt

    compile(self, optimizer, loss, metrics=None, loss_weights=None, sample_weight_mode=None)
    

    本函数编译模型以供训练,参数有

    optimizer:优化器,为预定义优化器名或优化器对象,参考优化器
    loss:损失函数,为预定义损失函数名或一个目标函数,参考损失函数
    metrics:列表,包含评估模型在训练和测试时的性能的指标,典型用法是metrics=[‘accuracy’]如果要在多输出模型中为不同的输出指定不同的指标,可像该参数传递一个字典,例如metrics={‘ouput_a’: ‘accuracy’}
    sample_weight_mode:如果你需要按时间步为样本赋权(2D权矩阵),将该值设为“temporal”。默认为“None”,代表按样本赋权(1D权)。
    如果模型有多个输出,可以向该参数传入指定sample_weight_mode的字典或列表。在下面fit函数的解释中有相关的参考内容。

    【Tips】如果你只是载入模型并利用其predict,可以不用进行compile。在Keras中,compile主要完成损失函数和优化器的一些配置,是为训练服务的。predict会在内部进行符号函数的编译工作(通过调用_make_predict_function生成函数)

    3 fit 模型训练参数设置 + 训练

    fit(self, x=None, y=None, batch_size=32, epochs=1, verbose=1, callbacks=None, validation_split=0.0, validation_data=None, shuffle=True, class_weight=None, sample_weight=None, initial_epoch=0)
    

    本函数用以训练模型,参数有:

    • x:输入数据。如果模型只有一个输入,那么x的类型是numpy
      array,如果模型有多个输入,那么x的类型应当为list,list的元素是对应于各个输入的numpy
      array。如果模型的每个输入都有名字,则可以传入一个字典,将输入名与其输入数据对应起来。
    • y:标签,numpy array。如果模型有多个输出,可以传入一个numpy
      array的list。如果模型的输出拥有名字,则可以传入一个字典,将输出名与其标签对应起来。
    • batch_size:整数,指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。
    • nb_epoch:整数,训练的轮数,训练数据将会被遍历nb_epoch次。Keras中nb开头的变量均为"number of"的意思
    • verbose:日志显示,0为不在标准输出流输出日志信息,1为输出进度条记录,2为每个epoch输出一行记录
    • callbacks:list,其中的元素是keras.callbacks.Callback的对象。这个list中的回调函数将会在训练过程中的适当时机被调用,参考回调函数
    • validation_split:0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之后,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。
    • validation_data:形式为(X,y)或(X,y,sample_weights)的tuple,是指定的验证集。此参数将覆盖validation_spilt。
    • shuffle:布尔值,表示是否在训练过程中每个epoch前随机打乱输入样本的顺序。
    • class_weight:字典,将不同的类别映射为不同的权值,该参数用来在训练过程中调整损失函数(只能用于训练)。该参数在处理非平衡的训练数据(某些类的训练样本数很少)时,可以使得损失函数对样本数不足的数据更加关注。
    • sample_weight:权值的numpy
      array,用于在训练时调整损失函数(仅用于训练)。可以传递一个1D的与样本等长的向量用于对样本进行1对1的加权,或者在面对时序数据时,传递一个的形式为(samples,sequence_length)的矩阵来为每个时间步上的样本赋不同的权。这种情况下请确定在编译模型时添加了sample_weight_mode=‘temporal’。
    • initial_epoch: 从该参数指定的epoch开始训练,在继续之前的训练时有用。

    输入数据与规定数据不匹配时会抛出错误

    fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况

    4.evaluate,模型评估

    evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None)
    

    本函数按batch计算在某些输入数据上模型的误差,其参数有:

    • x:输入数据,与fit一样,是numpy array或numpy array的list
    • y:标签,numpy array
    • batch_size:整数,含义同fit的同名参数
    • verbose:含义同fit的同名参数,但只能取0或1
    • sample_weight:numpy array,含义同fit的同名参数

    本函数返回一个测试误差的标量值(如果模型没有其他评价指标),或一个标量的list(如果模型还有其他的评价指标)。model.metrics_names将给出list中各个值的含义。

    如果没有特殊说明,以下函数的参数均保持与fit的同名参数相同的含义
    如果没有特殊说明,以下函数的verbose参数(如果有)均只能取0或1

    5.predict 模型预测

    predict(self, x, batch_size=32, verbose=0)
    
    

    本函数按batch获得输入数据对应的输出,其参数有:

    函数的返回值是预测值的numpy array

    模型检查 on_batch

    train_on_batch(self, x, y, class_weight=None, sample_weight=None)
    test_on_batch(self, x, y, sample_weight=None)
    predict_on_batch(self, x)
    

    train_on_batch:本函数在一个batch的数据上进行一次参数更新,函数返回训练误差的标量值或标量值的list,与evaluate的情形相同。
    test_on_batch:本函数在一个batch的样本上对模型进行评估,函数的返回与evaluate的情形相同;
    predict_on_batch:本函数在一个batch的样本上对模型进行测试,函数返回模型在一个batch上的预测结果

    _generator

    fit_generator(self, generator, steps_per_epoch, epochs=1, verbose=1, callbacks=None, validation_data=None, validation_steps=None, class_weight=None, max_q_size=10, workers=1, pickle_safe=False, initial_epoch=0)
    evaluate_generator(self, generator, steps, max_q_size=10, workers=1, pickle_safe=False)
    

    案例一:简单的单层-全连接网络

    from keras.layers import Input, Dense
    from keras.models import Model
    
    # This returns a tensor
    inputs = Input(shape=(784,))
    
    # a layer instance is callable on a tensor, and returns a tensor
    x = Dense(64, activation='relu')(inputs)
    # 输入inputs,输出x
    # (inputs)代表输入
    x = Dense(64, activation='relu')(x)
    # 输入x,输出x
    predictions = Dense(10, activation='softmax')(x)
    # 输入x,输出分类
    
    # This creates a model that includes
    # the Input layer and three Dense layers
    model = Model(inputs=inputs, outputs=predictions)
    model.compile(optimizer='rmsprop',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    model.fit(data, labels)  # starts training
    

    其中:
    可以看到结构与序贯模型完全不一样,其中x = Dense(64, activation=‘relu’)(inputs)中:(input)代表输入;x代表输出
    model = Model(inputs=inputs, outputs=predictions);该句是函数式模型的经典,可以同时输入两个input,然后输出output两个模型

    案例二:视频处理

    x = Input(shape=(784,))
    # This works, and returns the 10-way softmax we defined above.
    y = model(x)
    # model里面存着权重,然后输入x,输出结果,用来作fine-tuning
    
    # 分类->视频、实时处理
    from keras.layers import TimeDistributed
    
    # Input tensor for sequences of 20 timesteps,
    # each containing a 784-dimensional vector
    input_sequences = Input(shape=(20, 784))
    # 20个时间间隔,输入784维度的数据
    
    # This applies our previous model to every timestep in the input sequences.
    # the output of the previous model was a 10-way softmax,
    # so the output of the layer below will be a sequence of 20 vectors of size 10.
    processed_sequences = TimeDistributed(model)(input_sequences)
    # Model是已经训练好的
    

    其中:
    Model是已经训练好的,现在用来做迁移学习;
    其中还可以通过TimeDistributed来进行实时预测;
    TimeDistributed(model)(input_sequences),input_sequences代表序列输入;model代表已训练的模型

    案例三:双输入、双模型输出:LSTM 时序预测

    本案例很好,可以了解到Model的精髓在于他的任意性,给编译者很多的便利。

    输入:
    新闻语料;新闻语料对应的时间
    输出:
    新闻语料的预测模型;新闻语料+对应时间的预测模型
    这里写图片描述

    模型一:只针对新闻语料的LSTM模型

    from keras.layers import Input, Embedding, LSTM, Dense
    from keras.models import Model
    
    # Headline input: meant to receive sequences of 100 integers, between 1 and 10000.
    # Note that we can name any layer by passing it a "name" argument.
    main_input = Input(shape=(100,), dtype='int32', name='main_input')
    # 一个100词的BOW序列
    
    # This embedding layer will encode the input sequence
    # into a sequence of dense 512-dimensional vectors.
    x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)
    # Embedding层,把100维度再encode成512的句向量,10000指的是词典单词总数
    
    
    # A LSTM will transform the vector sequence into a single vector,
    # containing information about the entire sequence
    lstm_out = LSTM(32)(x)
    # ? 32什么意思?????????????????????
    
    #然后,我们插入一个额外的损失,使得即使在主损失很高的情况下,LSTM和Embedding层也可以平滑的训练。
    
    auxiliary_output = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)
    #再然后,我们将LSTM与额外的输入数据串联起来组成输入,送入模型中:
    # 模型一:只针对以上的序列做的预测模型
    

    组合模型:新闻语料+时序

    # 模型二:组合模型
    auxiliary_input = Input(shape=(5,), name='aux_input')  # 新加入的一个Input,5维度
    x = keras.layers.concatenate([lstm_out, auxiliary_input])   # 组合起来,对应起来
    
    
    # We stack a deep densely-connected network on top
    # 组合模型的形式
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    x = Dense(64, activation='relu')(x)
    # And finally we add the main logistic regression layer
    main_output = Dense(1, activation='sigmoid', name='main_output')(x)
    
    
    #最后,我们定义整个2输入,2输出的模型:
    model = Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])
    #模型定义完毕,下一步编译模型。
    #我们给额外的损失赋0.2的权重。我们可以通过关键字参数loss_weights或loss来为不同的输出设置不同的损失函数或权值。
    #这两个参数均可为Python的列表或字典。这里我们给loss传递单个损失函数,这个损失函数会被应用于所有输出上。
    
    

    其中:Model(inputs=[main_input, auxiliary_input], outputs=[main_output, auxiliary_output])是核心,
    Input两个内容,outputs两个模型

    # 训练方式一:两个模型一个loss
    model.compile(optimizer='rmsprop', loss='binary_crossentropy',
                  loss_weights=[1., 0.2])
    #编译完成后,我们通过传递训练数据和目标值训练该模型:
    
    model.fit([headline_data, additional_data], [labels, labels],
              epochs=50, batch_size=32)
    
    # 训练方式二:两个模型,两个Loss
    #因为我们输入和输出是被命名过的(在定义时传递了“name”参数),我们也可以用下面的方式编译和训练模型:
    model.compile(optimizer='rmsprop',
                  loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},
                  loss_weights={'main_output': 1., 'aux_output': 0.2})
    
    # And trained it via:
    model.fit({'main_input': headline_data, 'aux_input': additional_data},
              {'main_output': labels, 'aux_output': labels},
              epochs=50, batch_size=32)
    
    

    因为输入两个,输出两个模型,所以可以分为设置不同的模型训练参数

    案例四:共享层:对应关系、相似性

    一个节点,分成两个分支出去

    import keras
    from keras.layers import Input, LSTM, Dense
    from keras.models import Model
    
    tweet_a = Input(shape=(140, 256))
    tweet_b = Input(shape=(140, 256))
    #若要对不同的输入共享同一层,就初始化该层一次,然后多次调用它
    # 140个单词,每个单词256维度,词向量
    # 
    
    # This layer can take as input a matrix
    # and will return a vector of size 64
    shared_lstm = LSTM(64)
    # 返回一个64规模的向量
    
    # When we reuse the same layer instance
    # multiple times, the weights of the layer
    # are also being reused
    # (it is effectively *the same* layer)
    encoded_a = shared_lstm(tweet_a)
    encoded_b = shared_lstm(tweet_b)
    
    # We can then concatenate the two vectors:
        # 连接两个结果
        # axis=-1?????
    merged_vector = keras.layers.concatenate([encoded_a, encoded_b], axis=-1)
    
    # And add a logistic regression on top
    predictions = Dense(1, activation='sigmoid')(merged_vector)
    # 其中的1 代表什么????
    
    # We define a trainable model linking the
    # tweet inputs to the predictions
    model = Model(inputs=[tweet_a, tweet_b], outputs=predictions)
    
    model.compile(optimizer='rmsprop',
                  loss='binary_crossentropy',
                  metrics=['accuracy'])
    model.fit([data_a, data_b], labels, epochs=10)
    # 训练模型,然后预测
    

    案例五:抽取层节点内容

    # 1、单节点
    a = Input(shape=(140, 256))
    lstm = LSTM(32)
    encoded_a = lstm(a)
    assert lstm.output == encoded_a
    # 抽取获得encoded_a的输出张量
    
    # 2、多节点
    a = Input(shape=(140, 256))
    b = Input(shape=(140, 256))
    
    lstm = LSTM(32)
    encoded_a = lstm(a)
    encoded_b = lstm(b)
    
    assert lstm.get_output_at(0) == encoded_a
    assert lstm.get_output_at(1) == encoded_b
    
    # 3、图像层节点
    # 对于input_shape和output_shape也是一样,如果一个层只有一个节点,
    #或所有的节点都有相同的输入或输出shape,
    #那么input_shape和output_shape都是没有歧义的,并也只返回一个值。
    #但是,例如你把一个相同的Conv2D应用于一个大小为(3,32,32)的数据,
    #然后又将其应用于一个(3,64,64)的数据,那么此时该层就具有了多个输入和输出的shape,
    #你就需要显式的指定节点的下标,来表明你想取的是哪个了
    a = Input(shape=(3, 32, 32))
    b = Input(shape=(3, 64, 64))
    
    conv = Conv2D(16, (3, 3), padding='same')
    conved_a = conv(a)
    
    # Only one input so far, the following will work:
    assert conv.input_shape == (None, 3, 32, 32)
    
    conved_b = conv(b)
    # now the `.input_shape` property wouldn't work, but this does:
    assert conv.get_input_shape_at(0) == (None, 3, 32, 32)
    assert conv.get_input_shape_at(1) == (None, 3, 64, 64)
    

    案例六:视觉问答模型

    #这个模型将自然语言的问题和图片分别映射为特征向量,
    #将二者合并后训练一个logistic回归层,从一系列可能的回答中挑选一个。
    from keras.layers import Conv2D, MaxPooling2D, Flatten
    from keras.layers import Input, LSTM, Embedding, Dense
    from keras.models import Model, Sequential
    
    # First, let's define a vision model using a Sequential model.
    # This model will encode an image into a vector.
    vision_model = Sequential()
    vision_model.add(Conv2D(64, (3, 3) activation='relu', padding='same', input_shape=(3, 224, 224)))
    vision_model.add(Conv2D(64, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(128, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Conv2D(256, (3, 3), activation='relu', padding='same'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(Conv2D(256, (3, 3), activation='relu'))
    vision_model.add(MaxPooling2D((2, 2)))
    vision_model.add(Flatten())
    
    # Now let's get a tensor with the output of our vision model:
    image_input = Input(shape=(3, 224, 224))
    encoded_image = vision_model(image_input)
    
    # Next, let's define a language model to encode the question into a vector.
    # Each question will be at most 100 word long,
    # and we will index words as integers from 1 to 9999.
    question_input = Input(shape=(100,), dtype='int32')
    embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
    encoded_question = LSTM(256)(embedded_question)
    
    # Let's concatenate the question vector and the image vector:
    merged = keras.layers.concatenate([encoded_question, encoded_image])
    
    # And let's train a logistic regression over 1000 words on top:
    output = Dense(1000, activation='softmax')(merged)
    
    # This is our final model:
    vqa_model = Model(inputs=[image_input, question_input], outputs=output)
    
    # The next stage would be training this model on actual data.
    

    .

    延伸一:fine-tuning时如何加载No_top的权重

    如果你需要加载权重到不同的网络结构(有些层一样)中,例如fine-tune或transfer-learning,你可以通过层名字来加载模型:
    model.load_weights(‘my_model_weights.h5’, by_name=True)
    例如:

    假如原模型为:

        model = Sequential()
        model.add(Dense(2, input_dim=3, name="dense_1"))
        model.add(Dense(3, name="dense_2"))
        ...
        model.save_weights(fname)
    
    # new model
    model = Sequential()
    model.add(Dense(2, input_dim=3, name="dense_1"))  # will be loaded
    model.add(Dense(10, name="new_dense"))  # will not be loaded
    
    # load weights from first model; will only affect the first layer, dense_1.
    model.load_weights(fname, by_name=True)
    

    延伸二:应对不均衡样本的情况

    使用:class_weight,sample_weight

    两者的区别为:

    • class_weight—主要针对的上数据不均衡问题,比如:异常检测的二项分类问题,异常数据仅占1%,正常数据占99%; 此时就要设置不同类对loss的影响。

    • sample_weight—主要解决的是样本质量不同的问题,比如前1000个样本的可信度,那么它的权重就要高,后1000个样本可能有错、不可信,那么权重就要调低。

    class_weight的使用:

    cw = {0: 1, 1: 50}
    model.fit(x_train, y_train,batch_size=batch_size,epochs=epochs,verbose=1,callbacks=cbks,validation_data=(x_test, y_test), shuffle=True,class_weight=cw)
    

    sample_weight的使用:
    来源:https://www.kaggle.com/c/jigsaw-toxic-comment-classification-challenge/discussion/46673

    from sklearn.utils import class_weight
    
    list_classes = ["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]
    y = train[list_classes].values
    sample_weights = class_weight.compute_sample_weight('balanced', y)
    
    model.fit(X_t, y, batch_size=batch_size, epochs=epochs,validation_split=0.1,sample_weight=sample_weights, callbacks=callbacks_list)
    
    展开全文
  • 例题:请编写个函数fun,它的功能是:根据以下公式求π的值(要求满足精度0.0005,即某小于0.0005时停止迭代): 程序运后,如果输入精度0.0005,则程序输出为3.140578。 请勿改动主函数main与其它函数中的任何...

    例题:请编写一个函数fun,它的功能是:根据以下公式求π的值(要求满足精度0.0005,即某项小于0.0005时停止迭代):
    在这里插入图片描述
    程序运后,如果输入精度0.0005,则程序输出为3.140578。
    请勿改动主函数main与其它函数中的任何内容,仅在函数fun的花括号中填入所编写的若干语句。

    代码如下:

    #include<stdio.h>
    #include<math.h>
    double fun(double e)
    {
    	double s;
    	float n,t,pi;
    	t=1;pi=0;n=1.0;s=1.0;
    	while((fabs(s))>=e)
    	{
    		pi+=s;
    		t=n/(2*n+1);
    		s*=t;
    		n++;
    	}
    	pi=pi*2;
    	return pi;
    }
    main()
    {
    	double y;
    	FILE*out;
    	printf("Input e:");
    	scanf("%lf",&y);
    	printf("\ne=%lf,PI=%lf\n",y,fun(y));
    	out=fopen("outfile.dat","w");
    	fprintf(out,"e=%lf,PI=%lf\n",0.00003,fun(0.00003));
    	fclose(out);
    }
    

    输出运行窗口如下:
    在这里插入图片描述
    本周其他练习

    C语言程序设计专栏

    C语言编程>第九周 ① 下列程序定义了N×N的二维数组,并在主函数中自动赋值。请编写函数fun(int b[][N]),该函数的功能是:使数组左下半三角元素的值会全部置成0。

    C语言编程>第九周 ② 请编写一个函数unsigned(unsigned n),n是一个大于10的无符号整数,若n是m(m≥2)位的整数,则函数求出n的后m-1位的数作为函数值返回。

    C语言编程>第九周 ③ 请编写一个函数fun(char*str)该函数的功能是把字符串中的内容逆置。

    C语言编程>第九周 ④ 编写函数fun,它的功能是:利用以下所示的简单迭代方法求方程cos(y)-y=0的一个实根。yn+1=cos(yn)

    C语言编程>第九周 ⑤ 请编写一个函数fun,它的功能是:根据以下公式求π的值(要求满足精度0.0005,即某项小于0.0005时停止迭代):

    C语言编程>第九周 ⑥ 请编写一个函数fun,它的功能是:将s所指字符串中所有下标为奇数位置上的字母转换为小写(若该位置上下是字母,则不转换)。

    C语言编程>第九周 ⑦ 请编写一个函数fun,它的功能是:求出一个2×M整型二维数组中最小元素的值,并将最小值返回调用函数。

    C语言编程>第九周 ⑧ 请编写函数fun,其功能是:将两个两位数的正整数x、y合并成一个整数放在z中。合并的方式是:将x数的十位和个位依次放在z的千位和十位上,y的十位和个位依次放在z的百位和个位上。

    越努力越幸运!
    加油,奥力给!!!

    展开全文
  • throw runtime_error("open file to read failed"); string s; while(file >> s) { int pos = s.find(":"); if(s.substr(0, pos).compare("number") == 0)  number = s.substr(pos + 1); ...
  • 启动 打开文件 对话框,在 Visual c + + 中使用键盘快捷键或从 文件 菜单中将产生以下错误: 在 0x5003eaed DEVSHL.DLL 中访问冲突 (0xC0000005)。 DevShl.Dll 引用在 0x0000000 的内存。 无法读取该内存。 当...
  • Android笔记系列--Camera_FileProvider

    千次阅读 2018-01-30 10:15:53
    源码例子: ... FileProvider 在Android7.0版本上,Android系统强制执行了StrictMode API 政策,禁止向你的应用外公开File:...如果一项包含文件File://URI类型的Intent离开你的应用,应用失败,并出现FileUriExpose...
  • 只要你的等式里面有一个 string 对象,你就可以一直连续"+",但有一点需要保证的是,在开始的两项中,必须有一项是 string 对象。其原理很简单: 系统遇到"+"号,发现有一项是string 对象。 系统把另一项转化...
  • Android N 之前的 Uri ...其他的文件Uri是file://, 表示这个是个文件。这个uri是通过Uri.fromFile(File file)方法生成。 Android N 之前,这些uri可以传递到其他应用。 Android N 中共享文件 Android
  • 其中微软提出了个解决方案:FileTool.exe,微软官方下载地址和设置方法: http://support2.microsoft.com/kb/241396/zh-cn 。(以上这段是我自己写的)   概要 开始 打开文件 对话框中,在 ...
  • Python 生成临时文件和目录 -tempfile

    万次阅读 2018-07-06 10:59:40
    请看代码:官方文档 详见 tempfile- 生成临时文件和目录&gt;&gt;&gt; import tempfile # create a temporary file and write some data to it &gt;&gt;&gt; fp = tempfile.TemporaryFile()...
  • Android 7.0 FileProvider的使用

    万次阅读 2016-10-26 15:04:04
    我们使用手机的时候经常会看到应用程序提示升级,大部分应用内部都需要实现升级提醒和应用程序文件(APK文件)下载。 一般写法都差不多,比如在启动app的时候,通过api接口获得服务器最新的版本号,然后和...创建个serv
  • Mongodb 集群keyFile认证

    万次阅读 2017-03-11 18:12:25
    mongodb集群Replica Set模式,配置keyFile认证,预防黑客攻击
  • 1.概述 在实际工作中会经常遇到一些bug,有些就需要用到文件句柄,文件描述符等概念,比如报错: too many open files, 如果你对相关知识一无所知,那么debug...这系列的问题是我们不得不面对的。 博主通过翻...
  • Cannot open precompiled header file: Debug/****.pch: No such file or directory我的解决方案可以使用右键点击项目工程中的该cpp文件,选择setting,在c/c++栏,选择PreCompiled headers,然后设置第选项,选择...
  • Google——Google File System(GFS)

    万次阅读 2010-09-09 08:57:00
    Google文件系统(Google File System,GFS)是个大型的分布式文件系统。它为Google云计算提供海量存储,并且与Chubby、MapReduce以及Bigtable等技术结合十分紧密,处于所有核心技术的底层。由于GFS并不是个开源...
  • Microsoft Azure File 服务简介

    千次阅读 2015-01-13 17:01:15
    Microsoft Azure File 服务预览版。AzureFile 服务使用标准 SMB 2.1 协议提供文件共享。Azure中运行的应用程序现在可以使用熟悉的标准文件系统 API(如ReadFile 和 WriteFile)在虚拟机之间轻松共享文件。此外,您...
  • Can't write viminfo file /root/.viminfo!

    千次阅读 2012-10-15 14:43:10
    Can't write viminfo file /root/.viminfo! LinuxAdd comments 当使用vi编辑文件保存退出时报以下错误: E138: Can't write viminfo file /root/.viminfo! Hit ENTER or type command to continue ...
  • ROS专题----导航功能包navigation基础汇总

    万次阅读 多人点赞 2017-03-02 09:59:01
    资料来源ROS官网:http://wiki.ros.org/cn/navigation概述概念层面上讲,导航功能包集是相当...使用导航功能包集的先决条件是,机器人必须运行ROS,有个tf变换树,使用正确的ROS Message types发布传感器数据。而且
  • File-OS(简单文件系统的实现)

    万次阅读 多人点赞 2017-05-31 01:03:39
    前言期末的OS的大作业,写了个简单的文件管理系统,写了5天左右(实际整个项目历经个月...项目github地址https://github.com/qq1367212627/File-OS简单的介绍基本的功能是在磁盘上(D:/VitualDisk/)开辟个虚拟
  • FileProvider在Android N上的应用

    千次阅读 2017-04-03 16:02:29
    Android 从 N 开始不允许以 file:// 的方式通过 Intent 在两个 App 之间分享文件,取而代之的是通过 FileProvider 生成 content://Uri 。如果在 Android N 以上的版本继续使用 file:// 方式分享文件,则系统会直接抛...
  • Google File System(中文翻译)

    万次阅读 2005-11-10 00:12:00
    Google文件系统 GFS是个可扩展的分布式文件系统,用于大型的、分布式的、对大量数据进行访问的应用。它运行于廉价的普通硬件上,但可以提供容错功能。它可以给大量的用户提供总体性能较高的服务。 1、设计概览 (1...
  • HTML5 让 HTML 这个一度单纯的置标语言焕发出成熟的魅力,使之成为 Web 开发者的强力工具,W3C 近日又推出个新草案,HTML5 File API,这个 API 将让大大改善基于 Web 的文件上传操作,甚至可以实现直接将文件从...
  • FileStream fs = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Write); //创建个StreamWriter对象 StreamWriter sw = new StreamWriter(fs); sw.Write(this.textBox1.Text); //释放...
  • 介绍自从远古计绳结开始,数据库的存储就注定了今天的地位和多样性,Nosql的出现更是解决了现有的关系型数据库无法解决的一些难题,对高性能,灵活度,扩展性,...文章讲解的是如何搭建个安全认证的mongodb集群(安
  • 例题:编写函数fun,它的功能是:利用以下所示的简单迭代方法求方程cos(y)-y=0的个实根。 yn+1=cos(yn) 迭代步骤如下: (1)取y1初值为0.0。 (2)y0=y1,把y1的值赋给y0。 (3)y1=cos(y0),求出个新的y1。 (4)若y0-y1...
  • __FILE__, __FUNCTION__, __LINE__

    万次阅读 2012-05-05 09:26:34
    __FILE__, __FUNCTION__, __LINE__ 2008-07-25 19:19 9386人阅读 评论(1) 收藏 举报 调试常用的 __FILE__, __FUNCTION__, __LINE__ 调试常用的 __FILE__, __FUNCTION__, __LINE__ 没想到 ...
  • Java常用

    千次阅读 热门讨论 2014-04-04 17:36:25
    在马士兵的视频中,讲解了Java中常用的,主要包括字符串相关(String和StringBuffer )、基本数据类型包装、MathFile类以及枚举。字符串类型都是类型,java中的字符串都是对象,也就是说每...
  • iOS11开发新增功能大全

    万次阅读 2017-06-07 01:34:19
    iOS11开发新增功能大全 转载请标注出处 前言 2017年6月6日凌晨一点(北京时间),苹果在2017WWDC大会上发布了全新的iOS11系统。可能大家印象比较深刻的就是iOS11新增了增强现实的框架ARKit和安卓玩了几十年都玩烂了...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 211,134
精华内容 84,453
关键字:

以下哪一项不是file类的功能