Class の getPackageName() は、Java9 からであることに注意

ある程度の規模のプロジェクトまたは会社では、Java で開発といっても
未だに、Java 8 のままである。

だから以下のようなコードを書いても使うことができない。

自クラスと同じ場所(クラスパッケージ階層)に読込みたいリソースファイルを配置する設計の時、、

public static byte[] readBinary(String path) throws IOException {
   try{
      File file = Optional.ofNullable(
         ClassLoader.getSystemClassLoader()
         .getResource(Class.forName(Thread.currentThread()
         .getStackTrace()[2].getClassName())
         .getPackageName().replaceAll("\\.", "/") + "/" + path))
      .map(u->{
         try{
            return new File(u.toURI());
         }catch(URISyntaxException e){
            return null;
         }
      }).orElse(new File(path));
      try(InputStream in = new FileInputStream(file)){
         byte[] data = new byte[in.available()];
         in.read(data);
         in.close();
         return data;
      }
   }catch(ClassNotFoundException ex){
      throw new IOException(ex.getMessage(), ex);
   }
}

public static String readText(String path) throws IOException {
   try{
      File file = Optional.ofNullable(
         ClassLoader.getSystemClassLoader()
         .getResource(Class.forName(Thread.currentThread()
         .getStackTrace()[2].getClassName())
         .getPackageName().replaceAll("\\.", "/") + "/" + path))
      .map(u->{
            try{
               return new File(u.toURI());
            }catch(URISyntaxException e){
               return null;
            }
      }).orElse(new File(path));
      try(InputStream in = new FileInputStream(file);
         ByteArrayOutputStream out = new ByteArrayOutputStream()){
         in.transferTo(out);
         return out.toString();
      }
   }catch(ClassNotFoundException ex){
      throw new IOException(ex.getMessage(), ex);
   }
}

public static Reader getReader(String path) throws IOException {
   try{
      File file = Optional.ofNullable(
         ClassLoader.getSystemClassLoader()
         .getResource(Class.forName(Thread.currentThread()
         .getStackTrace()[2].getClassName())
         .getPackageName().replaceAll("\\.", "/") + "/" + path))
      .map(u->{
            try{
               return new File(u.toURI());
            }catch(URISyntaxException e){
               return null;
            }
      }).orElse(new File(path));
      return new FileReader(file);
   }catch(ClassNotFoundException ex){
      throw new IOException(ex.getMessage(), ex);
   }
}

public static Reader getReader(String path, Charset charset) throws IOException {
   try{
      File file = Optional.ofNullable(
         ClassLoader.getSystemClassLoader()
         .getResource(Class.forName(Thread.currentThread()
         .getStackTrace()[2].getClassName())
         .getPackageName().replaceAll("\\.", "/") + "/" + path))
      .map(u->{
            try{
               return new File(u.toURI());
            }catch(URISyntaxException e){
               return null;
            }
      }).orElse(new File(path));
      return new FileReader(file, charset);
   }catch(ClassNotFoundException ex){
      throw new IOException(ex.getMessage(), ex);
   }
}

これは、Java 8 では、java.lang.Class に、getPackageName() パッケージ名完全修飾名取得のメソッドが
存在しないので、上のコードを利用できない。

Java 9 から、getPackageName() が使えるので、Java 9 以降であれば上のコードは利用できる。