En este post vamos a ver como validar una cadena de texto y verificar que es un DNI o NIF válido.
Algoritmo para validar una cadena de texto como un DNI o NIF:
-
El string o cadena de texto debe tener una longitud de 9 caracteres
-
Los caracteres del 1 al 8 deben ser números
-
El último dígito (dígito de control) se calcula dividiendo el número del DNI entre 23. El resto de la división (operación normalmente conocida como módulo) indicará la letra que debe ocupar la posición 9 del string según la tabla siguiente:
Resto
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Letra
T
R
W
A
G
M
Y
F
P
D
X
B
N
J
Z
S
Q
V
H
L
C
K
E
-
Como punto extra, la administración indica que los siguientes DNI no son válidos independientemente que cumplan la validación explicada en los puntos anteriores: 00000000T, 00000001R y 99999999R.
Como validar un DNI en Java
Para validar en Java un DNI según el algoritmo explicado en el apartado anterior, simplemente deberíamos tener el siguiente código:
public class Validaciones {
private static final Pattern REGEXP = Pattern.compile("[0-9]{8}[A-Z]");
private static final String DIGITO_CONTROL = "TRWAGMYFPDXBNJZSQVHLCKE";
private static final String[] INVALIDOS = new String[] { "00000000T", "00000001R", "99999999R" };
public static boolean validarDNI(String dni) {
return Arrays.binarySearch(INVALIDOS, dni) < 0 // <1>
&& REGEXP.matcher(dni).matches() // <2>
&& dni.charAt(8) == DIGITO_CONTROL.charAt(Integer.parseInt(dni.substring(0, 8)) % 23); // <3>
}
}
-
Lo primero que hacemos es asegurarnos de que el string no es ninguno de los DNI no válidos que fija el Ministerio de Interior.
-
Después, mediante una expresión regular, validamos que el string tenga 8 números y una letra al final (en este punto, solo estamos validando que la cadena de texto esté bien formada).
-
Para terminar, no basta con que el último dígito sea una letra, tiene que cumplir que el último carácter se corresponda con el dígito de control de la tabla después de aplicar la operación módulo 23.
Para ver que realmente es correcto el algoritmo anterior, podríamos definir un test como el siguiente:
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.jupiter.api.Test;
class ValidacionesTest {
@Test
void validate_dni() {
// DNI que no son válidos por el Ministerio de interior
assertFalse(Validaciones.validarDNI("00000000T"));
assertFalse(Validaciones.validarDNI("00000001R"));
assertFalse(Validaciones.validarDNI("99999999R"));
// Strings que no cumplen la expresion regular
assertFalse(Validaciones.validarDNI("0123"));
assertFalse(Validaciones.validarDNI("01234a67Z"));
assertFalse(Validaciones.validarDNI("012345678-"));
assertFalse(Validaciones.validarDNI("0123456789"));
// DNI que si cumplen todas las validaciones
assertTrue(Validaciones.validarDNI("12345678Z"));
assertTrue(Validaciones.validarDNI("45673254S"));
assertTrue(Validaciones.validarDNI("72849506L"));
}
}
Como has podido comprobar al leer este post, validar un DNI en Java es muy sencillo.