code: public String read_string() throws OtpErlangDecodeException {
          int tag;
          int len;
          byte[] strbuf;
          int[] intbuf;
          tag = read1skip_version();
          switch (tag) {
          case OtpExternal.stringTag:
              len = read2BE();
              strbuf = new byte[len];
              this.readN(strbuf);
              return OtpErlangString.newString(strbuf);
          case OtpExternal.nilTag:
              return "";
          case OtpExternal.listTag: // List when unicode +
              len = read4BE();
              intbuf = new int[len];
              for (int i = 0; i < len; i++) {
                  intbuf[i] = read_int();
                  if (!OtpErlangString.isValidCodePoint(intbuf[i])) {
                      throw new OtpErlangDecodeException("Invalid CodePoint: "
                              + intbuf[i]);
                  }
              }
              read_nil();
              return new String(intbuf, 0, intbuf.length);
          default:
              throw new OtpErlangDecodeException(
                      "Wrong tag encountered, expected " + OtpExternal.stringTag
                              + " or " + OtpExternal.listTag + ", got " + tag);
          }
      }
docs: Read a string from the stream.
  
  @return the value of the string.
  
  @exception OtpErlangDecodeException
  if the next term in the stream is not a string.