【再考】escape がある区切り文字による split

先日書いた、
oboe2uran.hatenablog.com

これでは、ダメだ
エスケープする文字列が残らない。
だいたい java.util.StringTokenizer なんて古いものは、すでに奨励されていない。
char 型で処理する

public static List<String> tokenToList(String str, char sep, char escape){
   List<String> list = new ArrayList<>();
   StringBuilder sb = new StringBuilder();
   boolean isEscape = false;
   for(char c:str.toCharArray()) {
      if (isEscape) {
         isEscape = false;
      }else if(c==escape){
         isEscape = true;
         sb.append(c);
         continue;
      }else if(c==sep){
         list.add(sb.toString());
         sb.setLength(0);
         continue;
      }
      sb.append(c);
   }
   list.add(sb.toString());
   return list;
}

InputStream から生成

public static List<String> tokenToList(InputStream in, char sep, char escape) throws IOException{
   return tokenToList(new InputStreamReader(in, StandardCharsets.UTF_8), sep, escape);
}

public static List<String> tokenToList(InputStreamReader in, char sep, char escape) throws IOException{
   List<String> list = new ArrayList<>();
   StringBuilder sb = new StringBuilder();
   try{
      boolean isEscape = false;
      int i;
      while((i=in.read()) > 0){
         char c = (char)i;
         if (isEscape){
            isEscape = false;
         }else if(c==escape){
            isEscape = true;
            sb.append(c);
            continue;
         }else if(c==sep){
            list.add(sb.toString());
            sb.setLength(0);
            continue;
         }
         sb.append(c);
      }
      list.add(sb.toString());
   }catch(IOException e){
      throw e;
   }
   return list;
}

Stream<String> が欲しい

public static Stream<String> tokenToStream(String str, char sep, char escape){
   Stream.Builder<String> b = Stream.builder();
   StringBuilder sb = new StringBuilder();
   boolean isEscape = false;
   for(char c:str.toCharArray()) {
      if (isEscape) {
         isEscape = false;
      }else if(c==escape){
         isEscape = true;
         sb.append(c);
         continue;
      }else if(c==sep){
         b.add(sb.toString());
         sb.setLength(0);
         continue;
      }
      sb.append(c);
   }
   b.add(sb.toString());
   return b.build();
}

InputSteam から Stream<String> が欲しい

public static Stream<String> tokenToStream(InputStream in, char sep, char escape) throws IOException{
   return tokenToStream(new InputStreamReader(in, StandardCharsets.UTF_8), sep, escape);
}

public static Stream<String> tokenToStream(InputStreamReader in, char sep, char escape) throws IOException{
   Stream.Builder<String> b = Stream.builder();
   StringBuilder sb = new StringBuilder();
   try{
      boolean isEscape = false;
      int i;
      while((i=in.read()) > 0){
         char c = (char)i;
         if (isEscape){
            isEscape = false;
         }else if(c==escape){
            isEscape = true;
            sb.append(c);
            continue;
         }else if(c==sep){
            b.add(sb.toString());
            sb.setLength(0);
            continue;
         }
         sb.append(c);
      }
      b.add(sb.toString());
   }catch(IOException e){
      throw e;
   }
   return b.build();
}

これらで、注意すべきは、エスケープする文字、char で、'\0' を指定した時は、
String の spilit メソッド実行した時に取得できる配列と同じであることだ。


おそらく上のメソッドでそのような指定の実行はしないであろう。

この メソッドは、
GitHub - yipuran/yipuran-core: Java application framework
で、
org.yipuran.util.Tokenstring として作成した。