Java에서 int로 문자열 - 아마도 나쁜 데이터, 예외를 피해야합니다.

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

  •  05-07-2019
  •  | 
  •  

문제

Java가 무효 유형을 가지고 있지 않으며 tryparse ()도 없다고 생각합니다. 예외를 던지지 않고 입력 유효성 검사를 어떻게 처리합니까?

일반적인 방법 :

String userdata = /*value from gui*/
int val;
try
{
   val = Integer.parseInt(userdata);
}
catch (NumberFormatException nfe)
{
   // bad data - set to sentinel
   val = Integer.MIN_VALUE;
}

Regex를 사용하여 변형 가능한지 확인할 수 있지만 많은 오버 헤드처럼 보입니다.

이 상황을 처리하기위한 모범 사례는 무엇입니까?

편집 : 근거 : 예외 처리에 대한 많은 대화가 있었으며 일반적인 태도는 예기치 않은 시나리오에만 예외를 사용해야한다는 것입니다. 그러나 나는 잘못된 사용자 입력이 예상되지 않는다고 생각합니다. 예, 그것은 실제로 학문적 요점입니다.

추가 편집 :

답의 일부는 그렇게 잘못된 것을 정확하게 보여줍니다. 당신은 질문을받는 질문을 무시하고 그것과 관련이없는 또 다른 질문에 대답합니다. 질문은 레이어 간의 전환에 대해 묻지 않습니다. 질문은 번호가 부당하지 않은 경우 반환 할 내용을 묻지 않습니다. 당신이 아시다시피, val = integer.min_value; 이 완전히 컨텍스트 무료 코드 스 니펫이 가져온 응용 프로그램에 대한 올바른 옵션입니다.

도움이 되었습니까?

해결책

Min_Value를 반환하는 것은 의심의 여지가 있지만, 당신이 본질적으로 오류 코드로 사용하는 것이 옳은 일이라고 확신하지 않는 한, 그것은 거의 그것입니다. 그러나 최소한 오류 코드 동작을 문서화했습니다.

잘못된 입력을 기록하여 추적 할 수 있도록 유용 할 수도 있습니다.

다른 팁

나는 물었다 이 파싱을 수행하는 방법이있는 오픈 소스 유틸리티 라이브러리가있는 경우 그리고 대답은 예입니다!

에서 Apache Commons Lang 당신이 사용할 수있는 숫자 우틸 .toint:

// returns defaultValue if the string cannot be parsed.
int i = org.apache.commons.lang.math.NumberUtils.toInt(s, defaultValue);

에서 Google Guava 당신이 사용할 수있는 ints.tryparse:

// returns null if the string cannot be parsed
// Will throw a NullPointerException if the string is null
Integer i = com.google.common.primitives.Ints.tryParse(s);

예외를 던지지 않고 숫자를 구문 분석하기 위해 자신의 방법을 작성할 필요가 없습니다.

사용자 제공 데이터의 경우 Integer.parseint는 일반적으로 국제화를 지원하지 않기 때문에 잘못된 방법입니다. 그만큼 java.text 패키지는 당신의 (Verbose) 친구입니다.

try {
    NumberFormat format = NumberFormat.getIntegerInstance(locale);
    format.setParseIntegerOnly(true);
    format.setMaximumIntegerDigits(9);
    ParsePosition pos = new ParsePosition(0);
    int val = format.parse(str, pos).intValue();
    if (pos.getIndex() != str.length()) {
        // ... handle case of extraneous characters after digits ...
    }
    // ... use val ...
} catch (java.text.ParseFormatException exc) {
    // ... handle this case appropriately ...
}

접근 방식의 문제는 무엇입니까? 그런 식으로 그렇게하면 응용 프로그램의 성능이 전혀 해칠 것이라고 생각하지 않습니다. 그것이 올바른 방법입니다. 조기에 최적화하지 마십시오.

나는 그것이 나쁜 형태라고 확신하지만, 유틸리티 클래스에 일련의 정적 메소드가 있습니다. Utilities.tryParseInt(String value) 문자열이 기치 할 수없는 경우 0을 반환합니다 Utilities.tryParseInt(String value, int defaultValue) IF를 사용할 값을 지정할 수 있습니다. parseInt() 예외를 던집니다.

잘못된 입력에 알려진 값을 반환하는 것이 완벽하게 수용 될 때가 있다고 생각합니다. 매우 고안된 예 : YYYYMMDD 형식의 날짜를 사용자에게 요청하고 입력이 잘못됩니다. 같은 일을하는 것은 완벽하게 받아 들여질 수 있습니다 Utilities.tryParseInt(date, 19000101) 또는 Utilities.tryParseInt(date, 29991231); 프로그램 요구 사항에 따라.

나는 Stinkyminky가 게시물의 맨 아래로 향한 지점을 다시 만들 것입니다.

일반적으로 잘 받아 들여지는 접근 방식을 검증하는 사용자 입력 (또는 구성 파일의 입력 등)은 실제로 데이터를 처리하기 전에 유효성 검사를 사용하는 것입니다. ~ 안에 대부분 사례는, 이는 알고리즘을 구문 분석에 여러 번 호출 할 수 있지만 좋은 디자인 이동입니다.

사용자 입력을 올바르게 검증했다는 것을 알게되면 그 다음에 그것을 구문 분석하고 무시, 로그 또는 runtimeexception으로 숫자 formatexception으로 변환하는 것이 안전합니다.

이 접근법은 모델 (int 또는 float 형식의 값을 실제로 갖는 데 관심이있는 곳)과 사용자 인터페이스 모델 (사용자가 실제로 무엇이든 내도록 허용하는 경우 비즈니스 모델 (실제로 int 또는 float format)과 사용자 인터페이스 모델의 두 가지 조각으로 모델을 고려해야합니다. 원하다).

데이터가 사용자 인터페이스 모델에서 비즈니스 모델로 마이그레이션하려면 유효성 검사 단계를 통과해야합니다 (필드별로 필드에서 발생할 수 있지만 대부분의 시나리오는 구성중인 전체 개체에 대한 유효성 검사를 요구합니다). .

유효성 검사가 실패하면 사용자에게 잘못한 일을 알리는 피드백이 제시되어 문제를 해결할 수있는 기회가 주어집니다.

Jgoodies 바인딩 및 JSR 295와 같은 바인딩 라이브러리는 이러한 종류의 구현보다 훨씬 쉽게 구현하기가 훨씬 쉽게 만들어줍니다. 많은 웹 프레임 워크는 실제 비즈니스 모델과 분리 된 사용자 입력을 제공하는 구성을 제공하며, 유효성 검사 후 비즈니스 객체 만 채워집니다.

구성 파일의 유효성 검증 측면에서 (일부 주석에 제시된 다른 사용 사례), 특정 값이 전혀 지정되지 않은 경우 기본값을 지정하는 것이 한 가지이지만 데이터가 잘못된 경우 (누군가가 a. 오 ''Zero '대신 - 또는 MS Word에서 복사했거나 모든 백 틱이 펑키 유니 코드 문자를 얻었습니다), 어떤 종류의 시스템 피드백이 필요합니다 (런타임 예외를 던져서 앱을 실패하더라도). .

내가하는 방법은 다음과 같습니다.

public Integer parseInt(String data) {
  Integer val = null;
  try {
    val = Integer.parseInt(userdata);
  } catch (NumberFormatException nfe) { }
  return val;
}

그런 다음 NULL 신호가 유효하지 않은 데이터입니다. 기본값을 원한다면 다음으로 변경할 수 있습니다.

public Integer parseInt(String data,int default) {
  Integer val = default;
  try {
    val = Integer.parseInt(userdata);
  } catch (NumberFormatException nfe) { }
  return val;
}

모범 사례는 당신이 보여주는 코드라고 생각합니다.

나는 오버 헤드 때문에 Regex 대안을 가지지 않을 것입니다.

노력하다 org.apache.commons.lang.math.NumberUtils.createInteger(String s). 그것은 나에게 많은 도움이되었습니다. 복식, 긴 등에 대한 비슷한 방법이 있습니다.

정수를 사용할 수 있으며, 값이 나쁘면 Null로 설정할 수 있습니다. Java 1.6을 사용하는 경우 자동 권투/개봉을 제공합니다.

청정 시맨틱 (Java 8 OptionalInt)

Java 8+의 경우 Regex를 사용하여 프리 필터를 사용하여 (예외를 피하기 위해) 결과를 기본 옵션으로 랩핑 할 것입니다 ( "기본값"문제를 다루기 위해).

public static OptionalInt toInt(final String input) {
    return input.matches("[+-]?\\d+") 
            ? OptionalInt.of(Integer.parseInt(input)) 
            : OptionalInt.empty();
}

문자열 입력이 많은 경우 반환을 고려할 수 있습니다. IntStream 대신에 OptionalInt 당신이 할 수 있도록 flatMap().

참조

위의 코드는 다음과 같기 때문에 나쁘다.

// this is bad
int val = Integer.MIN_VALUE;
try
{
   val = Integer.parseInt(userdata);
}
catch (NumberFormatException ignoreException) { }

예외는 완전히 무시됩니다. 또한, 사용자는 -2147483648 (integer.min_value)을 통과 할 수 있기 때문에 마법 토큰이 나쁘다.

일반적인 구문 분석 가능한 질문은 유익하지 않습니다. 오히려 상황과 관련이 있어야합니다. 응용 프로그램에는 특정 요구 사항이 있습니다. 방법을 다음과 같이 정의 할 수 있습니다

private boolean isUserValueAcceptable(String userData)
{
   return (    isNumber(userData)    
          &&   isInteger(userData)   
          &&   isBetween(userData, Integer.MIN_VALUE, Integer.MAX_VALUE ) 
          );
}

요구 사항을 문서화 할 수 있고 잘 정의되고 테스트 가능한 규칙을 만들 수 있습니다.

당신이 말한 것처럼 미리 테스트하여 예외를 피할 수 있다면 (isparsable ()) 더 나을 수도 있지만 모든 라이브러리가 그를 염두에두고 설계된 것은 아닙니다.

나는 당신의 트릭을 사용했고 내 임베디드 시스템의 스택 트레이스가 당신이 그들을 잡든 아니든 인쇄되기 때문에 짜증납니다.

예외 메커니즘은 응답 값과 함께 상태 표시기를 얻는 유일한 방법이므로 가치가 있습니다. 또한 상태 표시기가 표준화됩니다. 오류가 있으면 예외가 발생합니다. 그렇게하면 오류 표시기를 직접 생각할 필요가 없습니다. 논쟁은 예외가 아니라 확인 된 예외가 아닙니다 (예 : 잡거나 선언 해야하는 것).

개인적으로 나는 당신이 예외가 실제로 가치있는 예 중 하나를 선택했다고 생각합니다. 사용자가 잘못된 값을 입력하는 일반적인 문제이며 일반적으로 올바른 값을 위해 사용자에게 돌아와야합니다. 사용자에게 요청하면 일반적으로 기본값으로 되돌아 가지 않습니다. 그것은 사용자에게 그의 입력 문제를 인상합니다.

예외를 다루고 싶지 않다면 runtimeexception (또는 파생 클래스)으로 마무리하면 코드의 예외를 무시하고 응용 프로그램이 발생할 때 신청서를 죽일 수 있습니다. 때로는 괜찮습니다).

NumberFormat 예외를 처리하는 방법에 대한 몇 가지 예 : 웹 앱 구성 데이터 :

loadCertainProperty(String propVal) {
  try
  {
    val = Integer.parseInt(userdata);
    return val;
  }
  catch (NumberFormatException nfe)
  { // RuntimeException need not be declared
    throw new RuntimeException("Property certainProperty in your configuration is expected to be " +
                               " an integer, but was '" + propVal + "'. Please correct your " +
                               "configuration and start again");
    // After starting an enterprise application the sysadmin should always check availability
    // and can now correct the property value
  }
}

GUI에서 :

public int askValue() {
  // TODO add opt-out button; see Swing docs for standard dialog handling
  boolean valueOk = false;
  while(!valueOk) {
    try {
      String val = dialog("Please enter integer value for FOO");
      val = Integer.parseInt(userdata);
      return val; 
    } catch (NumberFormatException nfe) {
      // Ignoring this; I don't care how many typo's the customer makes
    }
  }
}

웹 양식 : 유용한 오류 메시지와 수정 기회가있는 양식을 사용자에게 반환하십시오. 대부분의 프레임 워크는 표준화 된 검증 방법을 제공합니다.

integer.min_value as numberformatexception은 나쁜 생각입니다.

프로젝트 코인에 제안서를 추가 하여이 방법을 정수에 추가 할 수 있습니다.

@Nullable Public STATIC INTEGER PARSEINTEGER (String SRC) ... 잘못된 입력을 위해 NULL을 반환합니다.

그런 다음 여기에 귀하의 제안에 대한 링크를 넣으면 우리 모두가 투표 할 것입니다!

추신 : 이것을보십시오http://msdn.microsoft.com/en-us/library/bb397679.aspx이것이 얼마나 추악하고 부풀어 올릴 수 있는지입니다

그 앞에 약간의 진술을 넣으십시오. if (null! = userData)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top