جافا - كيفية معرفة ما إذا كان اسم ملف غير صالحة ؟ [مكررة]

StackOverflow https://stackoverflow.com/questions/893977

  •  23-08-2019
  •  | 
  •  

سؤال

في تطبيق جافا أنا إعادة تسمية الملفات إلى اسم ملف المقدمة في سلسلة المعلمة.هناك طريقة

boolean OKtoRename(String oldName, String newName)

الأساس الذي يتحقق إذا كان newName ليس اتخذت بالفعل من قبل بعض الملفات الأخرى, كما لا أريد أن أدفن تلك القائمة.

الآن خطر لي أنه ربما newName سلسلة لا دلالة اسم ملف صالح.حتى فكرت في إضافة هذا الاختيار إلى الأسلوب:

if (new File(newName).isFile()) { 
    return false; 
}

والتي من الواضح أنها ليست الطريقة الصحيحة للقيام بذلك ، لأنه في معظم الحالات newFile لا توجد حتى الآن وبالتالي على الرغم من أنه هو OKtoRename الدالة بإرجاع خطأ.

كنت أتسائل هل هناك طريقة (أعلم أنه ليس جافا.io.الملف الكائنات) مثل canExist()?أو أن تضطر إلى اللجوء إلى التعابير المنطقية للتأكد من newFile سلسلة لا تحتوي على أحرف غير صالحة (على سبيل المثال?, *, ", :)?وأتساءل عما إذا كان هناك ربما وظيفة مخبأة في مكان ما في JDK أن تقول لي إذا كانت السلسلة يمكن أن دلالة اسم ملف صالح.

هل كانت مفيدة؟

المحلول

استخدام createNewFile(), والتي سوف الذرة إنشاء الملف فقط اذا لا يوجد بعد.

إذا كان يتم إنشاء ملف باسم صالحة وليس من المتاح ملف موجود.ثم يمكنك فتح الملفات وكفاءة نسخ البيانات من واحدة إلى أخرى مع FileChannel.transferXXX عمليات.

الشيء المهم أن نأخذ في الاعتبار أن الشيك إنشاء ينبغي الذرية.إذا عليك أولا التحقق ما إذا كانت عملية آمنة ، ثم تنفيذ العملية بمثابة خطوة منفصلة ، الظروف قد تغيرت في الوقت الحالي, مما يجعل العملية غير آمنة.

إضافية للتفكير في ذات بوست: "نقل/نسخ العمليات في جافا".


تحديث:

لأن هذا الجواب ، NIO.2 واجهات برمجة التطبيقات أدخلت التي تضيف المزيد من التفاعل مع نظام الملفات.

افترض أن لديك برنامج تفاعلي و ترغب في التحقق بعد كل ضغطة ما إذا كان الملف هو يحتمل أن تكون صالحة.على سبيل المثال, قد تحتاج إلى تمكين زر "حفظ" فقط عند دخول صالحة بدلا من أن يظهر مربع حوار خطأ بعد الضغط على "حفظ".خلق وضمان حذف الكثير من الملفات غير الضرورية التي اقتراحي أعلاه يتطلب يبدو في حالة من الفوضى.

مع NIO.2, لا يمكنك إنشاء Path على سبيل المثال تحتوي على أحرف غير قانونية على نظام الملفات.وهو InvalidPathException أثيرت في أقرب وقت كما كنت في محاولة لخلق Path.

ومع ذلك ، ليس هناك API للتحقق من غير أسماء يتألف من الأحرف الصالحة ، مثل "PRN" على نظام التشغيل ويندوز.كحل التجارب أظهرت أن استخدام غير اسم الملف من شأنه أن يرفع متميزة استثناء عند محاولة الوصول إلى سمات (باستخدام Files.getLastModifiedTime(), على سبيل المثال).

إذا قمت بتحديد القانونية اسم ملف موجود, يمكنك الحصول على استثناء.

إذا قمت بتحديد القانونية اسم ملف غير موجود ، فإنه يثير NoSuchFileException.

إذا قمت بتحديد غير الاسم ، FileSystemException هو المطروحة.

ومع ذلك ، يبدو هذا جدا kludgey و قد لا تكون موثوقة على أنظمة التشغيل الأخرى.

نصائح أخرى

قمت بتجميع قائمة أحرف اسم الملف غير القانونية (بالنظر إلى أنظمة UNIX و Mac OS X و Windows) بناء على بعض البحوث عبر الإنترنت قبل شهرين. إذا كان اسم الملف الجديد يحتوي على أي من هذه، فهناك خطر قد لا يكون صالحا على جميع المنصات.

private static final char[] ILLEGAL_CHARACTERS = { '/', '\n', '\r', '\t', '\0', '\f', '`', '?', '*', '\\', '<', '>', '|', '\"', ':' };

تعديل:أود التأكيد، أن هذا هو ليس حل كامل: كما أشار المعلق، على الرغم من أن ذلك يمر هذا الاختبار قد لا يزال اسم الملف الخاص بك يمكن أن يكون كلمة أساسية خاصة بنظام Windows مثل COM، PRN، وما إلى ذلك، إذا كان اسم الملف الخاص بك يحتوي على أي من هذه الأحرف، فسيؤدي بالتأكيد إلى مشكلة في الصليب البيئة --Platform.

هنا يتم اقتراح طريقة النظام المحددة.

public static boolean isFilenameValid(String file) {
  File f = new File(file);
  try {
    f.getCanonicalPath();
    return true;
  } catch (IOException e) {
    return false;
  }
}

إذا تطور للكسوف، تحقق من org.eclipse.core.internal.resources.OS

public abstract class OS {
   private static final String INSTALLED_PLATFORM;

   public static final char[] INVALID_RESOURCE_CHARACTERS;
   private static final String[] INVALID_RESOURCE_BASENAMES;
   private static final String[] INVALID_RESOURCE_FULLNAMES;

   static {
      //find out the OS being used
      //setup the invalid names
      INSTALLED_PLATFORM = Platform.getOS();
      if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) {
         //valid names and characters taken from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp
         INVALID_RESOURCE_CHARACTERS = new char[] {'\\', '/', ':', '*', '?', '"', '<', '>', '|'};
         INVALID_RESOURCE_BASENAMES = new String[] {"aux", "com1", "com2", "com3", "com4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ 
               "com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$
               "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$
         Arrays.sort(INVALID_RESOURCE_BASENAMES);
         //CLOCK$ may be used if an extension is provided
         INVALID_RESOURCE_FULLNAMES = new String[] {"clock$"}; //$NON-NLS-1$
      } else {
         //only front slash and null char are invalid on UNIXes
         //taken from http://www.faqs.org/faqs/unix-faq/faq/part2/section-2.html
         INVALID_RESOURCE_CHARACTERS = new char[] {'/', '\0',};
         INVALID_RESOURCE_BASENAMES = null;
         INVALID_RESOURCE_FULLNAMES = null;
      }
   }

   /**
    * Returns true if the given name is a valid resource name on this operating system,
    * and false otherwise.
    */
   public static boolean isNameValid(String name) {
      //. and .. have special meaning on all platforms
      if (name.equals(".") || name.equals("..")) //$NON-NLS-1$ //$NON-NLS-2$
         return false;
      if (INSTALLED_PLATFORM.equals(Platform.OS_WIN32)) {
         //empty names are not valid
         final int length = name.length();
         if (length == 0)
            return false;
         final char lastChar = name.charAt(length-1);
         // filenames ending in dot are not valid
         if (lastChar == '.')
            return false;
         // file names ending with whitespace are truncated (bug 118997)
         if (Character.isWhitespace(lastChar))
            return false;
         int dot = name.indexOf('.');
         //on windows, filename suffixes are not relevant to name validity
         String basename = dot == -1 ? name : name.substring(0, dot);
         if (Arrays.binarySearch(INVALID_RESOURCE_BASENAMES, basename.toLowerCase()) >= 0)
            return false;
         return Arrays.binarySearch(INVALID_RESOURCE_FULLNAMES, name.toLowerCase()) < 0;
      }
      return true;
   }
}

هذه هي الطريقة التي قمت بتنفيذها:

public boolean isValidFileName(final String aFileName) {
    final File aFile = new File(aFileName);
    boolean isValid = true;
    try {
        if (aFile.createNewFile()) {
            aFile.delete();
        }
    } catch (IOException e) {
        isValid = false;
    }
    return isValid;
}

بالنسبة لي يبدو أن مشكلة في نظام التشغيل. قد ترغب ببساطة في التحقق من وجود بعض الأحرف غير الصحيحة في اسم الملف. يقوم Windows بهذا عند محاولة إعادة تسمية الملف، فإنه ينبثق رسالة تفيد بأن الملف لا يمكن أن يحتوي على أي من الأحرف التالية: /: *؟ <> | لست متأكدا مما إذا كان سؤالك هو "هل هناك مكتبة تفعل المهمة بالنسبة لي؟" في هذه الحالة لا أعرف أي.

مجرد شيء وجدته، في جافا 7 ثم في وقت لاحق، هناك فئة تسمى Paths التي لديها طريقة تسمى get التي تأخذ واحدة أو أكثر StringS و therows.

InvalidPathException - إذا كانت سلسلة المسار لا يمكن تحويلها إلى مسار

استخدام

String validName = URLEncoder.encode( fileName , "UTF-8");

File newFile = new File( validName );

هل العمل.

لقد وجدت للتو اليوم. لست متأكدا مما إذا كان يعمل بنسبة 100٪ من الوقت، ولكن حتى الآن، تمكنت من إنشاء أسماء ملفات صالحة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top